Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F33032559
D9367.1768405113.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D9367.1768405113.diff
View Options
diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs
--- a/services/identity/src/client_service.rs
+++ b/services/identity/src/client_service.rs
@@ -12,19 +12,19 @@
// Workspace crate imports
use crate::client_service::client_proto::{
- inbound_keys_for_user_request::Identifier, AddReservedUsernamesRequest,
- DeleteUserRequest, Empty, GenerateNonceResponse, InboundKeyInfo,
- InboundKeysForUserRequest, InboundKeysForUserResponse, LogoutRequest,
- OpaqueLoginFinishRequest, OpaqueLoginFinishResponse, OpaqueLoginStartRequest,
- OpaqueLoginStartResponse, OutboundKeysForUserRequest,
- OutboundKeysForUserResponse, RefreshUserPreKeysRequest,
- RegistrationFinishRequest, RegistrationFinishResponse,
- RegistrationStartRequest, RegistrationStartResponse,
- RemoveReservedUsernameRequest, ReservedRegistrationStartRequest,
- UpdateUserPasswordFinishRequest, UpdateUserPasswordStartRequest,
- UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest,
- VerifyUserAccessTokenRequest, VerifyUserAccessTokenResponse,
- WalletLoginRequest, WalletLoginResponse,
+ inbound_keys_for_user_request, outbound_keys_for_user_request,
+ AddReservedUsernamesRequest, DeleteUserRequest, Empty, GenerateNonceResponse,
+ InboundKeyInfo, InboundKeysForUserRequest, InboundKeysForUserResponse,
+ LogoutRequest, OpaqueLoginFinishRequest, OpaqueLoginFinishResponse,
+ OpaqueLoginStartRequest, OpaqueLoginStartResponse, OutboundKeyInfo,
+ OutboundKeysForUserRequest, OutboundKeysForUserResponse,
+ RefreshUserPreKeysRequest, RegistrationFinishRequest,
+ RegistrationFinishResponse, RegistrationStartRequest,
+ RegistrationStartResponse, RemoveReservedUsernameRequest,
+ ReservedRegistrationStartRequest, UpdateUserPasswordFinishRequest,
+ UpdateUserPasswordStartRequest, UpdateUserPasswordStartResponse,
+ UploadOneTimeKeysRequest, VerifyUserAccessTokenRequest,
+ VerifyUserAccessTokenResponse, WalletLoginRequest, WalletLoginResponse,
};
use crate::config::CONFIG;
use crate::database::{DatabaseClient, Device, KeyPayload};
@@ -786,9 +786,51 @@
async fn get_outbound_keys_for_user(
&self,
- _request: tonic::Request<OutboundKeysForUserRequest>,
+ request: tonic::Request<OutboundKeysForUserRequest>,
) -> Result<tonic::Response<OutboundKeysForUserResponse>, tonic::Status> {
- unimplemented!();
+ let message = request.into_inner();
+
+ use outbound_keys_for_user_request::Identifier;
+ let (user_ident, auth_type) = match message.identifier {
+ None => {
+ return Err(tonic::Status::invalid_argument("no identifier provided"))
+ }
+ Some(Identifier::Username(username)) => (username, AuthType::Password),
+ Some(Identifier::WalletAddress(address)) => (address, AuthType::Wallet),
+ };
+
+ let devices_map = self
+ .client
+ .get_keys_for_user(user_ident, &auth_type, true)
+ .await
+ .map_err(handle_db_error)?
+ .ok_or_else(|| match auth_type {
+ AuthType::Password => tonic::Status::not_found("username not found"),
+ AuthType::Wallet => {
+ tonic::Status::not_found("wallet address not found")
+ }
+ })?;
+
+ let transformed_devices = devices_map
+ .into_iter()
+ .filter_map(|(key, device_info)| {
+ let device_info_with_auth = DeviceInfoWithAuth {
+ device_info,
+ auth_type: &auth_type,
+ };
+ match OutboundKeyInfo::try_from(device_info_with_auth) {
+ Ok(key_info) => Some((key, key_info)),
+ Err(_) => {
+ error!("Failed to transform device info for key {}", key);
+ None
+ }
+ }
+ })
+ .collect::<HashMap<_, _>>();
+
+ Ok(tonic::Response::new(OutboundKeysForUserResponse {
+ devices: transformed_devices,
+ }))
}
async fn get_inbound_keys_for_user(
@@ -797,6 +839,7 @@
) -> Result<tonic::Response<InboundKeysForUserResponse>, tonic::Status> {
let message = request.into_inner();
+ use inbound_keys_for_user_request::Identifier;
let (user_ident, auth_type) = match message.identifier {
None => {
return Err(tonic::Status::invalid_argument("no identifier provided"))
@@ -807,7 +850,7 @@
let devices_map = self
.client
- .get_keys_for_user(user_ident, &auth_type)
+ .get_keys_for_user(user_ident, &auth_type, false)
.await
.map_err(handle_db_error)?
.ok_or_else(|| match auth_type {
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
@@ -100,6 +100,10 @@
pub const ONE_TIME_KEY: &str = SORT_KEY;
}
+// One-time key constants for device info map
+pub const CONTENT_ONE_TIME_KEY: &str = "contentOneTimeKey";
+pub const NOTIF_ONE_TIME_KEY: &str = "notifOneTimeKey";
+
// Tokio
pub const MPSC_CHANNEL_BUFFER_CAPACITY: usize = 1;
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
@@ -24,11 +24,12 @@
ACCESS_TOKEN_SORT_KEY, ACCESS_TOKEN_TABLE,
ACCESS_TOKEN_TABLE_AUTH_TYPE_ATTRIBUTE, ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE,
ACCESS_TOKEN_TABLE_PARTITION_KEY, ACCESS_TOKEN_TABLE_TOKEN_ATTRIBUTE,
- ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE, NONCE_TABLE,
+ ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE, CONTENT_ONE_TIME_KEY, NONCE_TABLE,
NONCE_TABLE_CREATED_ATTRIBUTE, NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE,
NONCE_TABLE_EXPIRATION_TIME_UNIX_ATTRIBUTE, NONCE_TABLE_PARTITION_KEY,
- RESERVED_USERNAMES_TABLE, RESERVED_USERNAMES_TABLE_PARTITION_KEY,
- USERS_TABLE, USERS_TABLE_DEVICES_ATTRIBUTE,
+ NOTIF_ONE_TIME_KEY, RESERVED_USERNAMES_TABLE,
+ RESERVED_USERNAMES_TABLE_PARTITION_KEY, USERS_TABLE,
+ USERS_TABLE_DEVICES_ATTRIBUTE,
USERS_TABLE_DEVICES_MAP_CONTENT_ONE_TIME_KEYS_ATTRIBUTE_NAME,
USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_ATTRIBUTE_NAME,
USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_SIGNATURE_ATTRIBUTE_NAME,
@@ -325,12 +326,12 @@
.await?;
debug!(
- "Able to get notif key for keyserver {}: {}",
+ "Able to get notif one-time key for keyserver {}: {}",
keyserver_id,
notif_one_time_key.is_some()
);
debug!(
- "Able to get content key for keyserver {}: {}",
+ "Able to get content one-time key for keyserver {}: {}",
keyserver_id,
content_one_time_key.is_some()
);
@@ -382,8 +383,8 @@
Ok(Some(outbound_payload))
}
- /// Will "mint" a single one time key by attempting to successfully deleting
- /// a key
+ /// Will "mint" a single one-time key by attempting to successfully delete a
+ /// key
pub async fn get_one_time_key(
&self,
device_id: &str,
@@ -395,14 +396,8 @@
let query_result = self.get_one_time_keys(device_id, account_type).await?;
let items = query_result.items();
- // If no one time keys exists, return none early
- let Some(item_vec) = items else {
- debug!("Unable to find {:?} one time key", account_type);
- return Ok(None);
- };
-
- if item_vec.len() < ONE_TIME_KEY_MINIMUM_THRESHOLD {
- // Avoid device_id being moved out-of-scope by "move"
+ fn spawn_refresh_keys_task(device_id: &str) {
+ // Clone the string slice to move into the async block
let device_id = device_id.to_string();
tokio::spawn(async move {
debug!("Attempting to request more keys for device: {}", &device_id);
@@ -412,9 +407,22 @@
});
}
+ // If no one-time keys exist, or if there aren't enough, request more.
+ // Additionally, if no one-time keys exist, return early.
+ let item_vec = if let Some(items_list) = items {
+ if items_list.len() < ONE_TIME_KEY_MINIMUM_THRESHOLD {
+ spawn_refresh_keys_task(device_id);
+ }
+ items_list
+ } else {
+ debug!("Unable to find {:?} one-time key", account_type);
+ spawn_refresh_keys_task(device_id);
+ return Ok(None);
+ };
+
let mut result = None;
- // Attempt to delete the one time keys individually, a successful delete
- // mints the one time key to the requester
+ // Attempt to delete the one-time keys individually, a successful delete
+ // mints the one-time key to the requester
for item in item_vec {
let pk = item.get_string(otk_table::PARTITION_KEY)?;
let otk = item.get_string(otk_table::SORT_KEY)?;
@@ -956,6 +964,7 @@
&self,
user_info: String,
auth_type: &AuthType,
+ get_one_time_keys: bool,
) -> Result<Option<Devices>, Error> {
let Some(mut user) =
self.get_user_from_user_info(user_info, auth_type).await?
@@ -989,6 +998,23 @@
device_info_string_map.insert(attribute_name, attribute_value_str);
}
+ if get_one_time_keys {
+ if let Some(notif_one_time_key) = self
+ .get_one_time_key(&device_id_key, OlmAccountType::Notification)
+ .await?
+ {
+ device_info_string_map
+ .insert(NOTIF_ONE_TIME_KEY.to_string(), notif_one_time_key);
+ }
+ if let Some(content_one_time_key) = self
+ .get_one_time_key(&device_id_key, OlmAccountType::Content)
+ .await?
+ {
+ device_info_string_map
+ .insert(CONTENT_ONE_TIME_KEY.to_string(), content_one_time_key);
+ }
+ }
+
devices_response.insert(device_id_key, device_info_string_map);
}
diff --git a/services/identity/src/grpc_utils.rs b/services/identity/src/grpc_utils.rs
--- a/services/identity/src/grpc_utils.rs
+++ b/services/identity/src/grpc_utils.rs
@@ -4,8 +4,11 @@
use tracing::error;
use crate::{
- client_service::client_proto::{IdentityKeyInfo, InboundKeyInfo, PreKey},
+ client_service::client_proto::{
+ IdentityKeyInfo, InboundKeyInfo, OutboundKeyInfo, PreKey,
+ },
constants::{
+ CONTENT_ONE_TIME_KEY, NOTIF_ONE_TIME_KEY,
USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_ATTRIBUTE_NAME,
USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_SIGNATURE_ATTRIBUTE_NAME,
USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_ATTRIBUTE_NAME,
@@ -24,53 +27,56 @@
}
impl TryFrom<DeviceInfoWithAuth<'_>> for InboundKeyInfo {
- type Error = tonic::Status;
+ type Error = Status;
fn try_from(data: DeviceInfoWithAuth) -> Result<Self, Self::Error> {
let mut device_info = data.device_info;
- let payload = extract_key(
- &mut device_info,
- USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_ATTRIBUTE_NAME,
- )?;
- let payload_signature = extract_key(
- &mut device_info,
- USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_SIGNATURE_ATTRIBUTE_NAME,
- )?;
-
- let social_proof =
- device_info.remove(USERS_TABLE_DEVICES_MAP_SOCIAL_PROOF_ATTRIBUTE_NAME);
- if social_proof.is_none() && data.auth_type == &AuthType::Wallet {
- error!("Social proof missing for wallet user");
- return Err(tonic::Status::failed_precondition(
- "Database item malformed",
- ));
- }
-
- let identity_info = IdentityKeyInfo {
- payload,
- payload_signature,
- social_proof,
- };
-
- let mut create_prekey =
- |key_attr, signature_attr| -> Result<PreKey, Status> {
- Ok(PreKey {
- pre_key: extract_key(&mut device_info, key_attr)?,
- pre_key_signature: extract_key(&mut device_info, signature_attr)?,
- })
- };
+ let identity_info =
+ extract_identity_info(&mut device_info, &data.auth_type)?;
Ok(InboundKeyInfo {
identity_info: Some(identity_info),
content_prekey: Some(create_prekey(
+ &mut device_info,
+ USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_ATTRIBUTE_NAME,
+ USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_SIGNATURE_ATTRIBUTE_NAME,
+ )?),
+ notif_prekey: Some(create_prekey(
+ &mut device_info,
+ USERS_TABLE_DEVICES_MAP_NOTIF_PREKEY_ATTRIBUTE_NAME,
+ USERS_TABLE_DEVICES_MAP_NOTIF_PREKEY_SIGNATURE_ATTRIBUTE_NAME,
+ )?),
+ })
+ }
+}
+
+impl TryFrom<DeviceInfoWithAuth<'_>> for OutboundKeyInfo {
+ type Error = Status;
+
+ fn try_from(data: DeviceInfoWithAuth) -> Result<Self, Self::Error> {
+ let mut device_info = data.device_info;
+
+ let identity_info =
+ extract_identity_info(&mut device_info, &data.auth_type)?;
+
+ let content_one_time_key = device_info.remove(CONTENT_ONE_TIME_KEY);
+ let notif_one_time_key = device_info.remove(NOTIF_ONE_TIME_KEY);
+
+ Ok(OutboundKeyInfo {
+ identity_info: Some(identity_info),
+ content_prekey: Some(create_prekey(
+ &mut device_info,
USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_ATTRIBUTE_NAME,
USERS_TABLE_DEVICES_MAP_CONTENT_PREKEY_SIGNATURE_ATTRIBUTE_NAME,
)?),
notif_prekey: Some(create_prekey(
+ &mut device_info,
USERS_TABLE_DEVICES_MAP_NOTIF_PREKEY_ATTRIBUTE_NAME,
USERS_TABLE_DEVICES_MAP_NOTIF_PREKEY_SIGNATURE_ATTRIBUTE_NAME,
)?),
+ one_time_content_prekey: content_one_time_key,
+ one_time_notif_prekey: notif_one_time_key,
})
}
}
@@ -84,3 +90,40 @@
Status::failed_precondition("Database item malformed")
})
}
+
+fn extract_identity_info(
+ device_info: &mut HashMap<String, String>,
+ auth_type: &AuthType,
+) -> Result<IdentityKeyInfo, Status> {
+ let payload = extract_key(
+ device_info,
+ USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_ATTRIBUTE_NAME,
+ )?;
+ let payload_signature = extract_key(
+ device_info,
+ USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_SIGNATURE_ATTRIBUTE_NAME,
+ )?;
+ let social_proof =
+ device_info.remove(USERS_TABLE_DEVICES_MAP_SOCIAL_PROOF_ATTRIBUTE_NAME);
+ if social_proof.is_none() && auth_type == &AuthType::Wallet {
+ error!("Social proof missing for wallet user");
+ return Err(Status::failed_precondition("Database item malformed"));
+ }
+
+ Ok(IdentityKeyInfo {
+ payload,
+ payload_signature,
+ social_proof,
+ })
+}
+
+fn create_prekey(
+ device_info: &mut HashMap<String, String>,
+ key_attr: &str,
+ signature_attr: &str,
+) -> Result<PreKey, Status> {
+ Ok(PreKey {
+ pre_key: extract_key(device_info, key_attr)?,
+ pre_key_signature: extract_key(device_info, signature_attr)?,
+ })
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 14, 3:38 PM (6 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5932696
Default Alt Text
D9367.1768405113.diff (13 KB)
Attached To
Mode
D9367: [identity] implement getOutboundKeysForUser
Attached
Detach File
Event Timeline
Log In to Comment