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 @@ -1951,8 +1951,72 @@ use std::{cmp::Ordering, collections::HashSet}; use tracing::{debug, error, info}; + use crate::constants::tonic_status_messages; + use super::*; + pub enum UserLoginFlow { + SignedDeviceListFlow, + V1Flow, + } + + impl UserLoginFlow { + pub fn is_signed_device_list_flow(&self) -> bool { + matches!(self, Self::SignedDeviceListFlow) + } + + pub fn is_v1_flow(&self) -> bool { + matches!(self, Self::V1Flow) + } + } + + impl DatabaseClient { + pub async fn get_user_login_flow( + &self, + user_id: &str, + ) -> Result<UserLoginFlow, Error> { + let history = self.get_device_list_history(user_id, None).await?; + let Some(last_update) = history.last() else { + error!( + user_id = redact_sensitive_data(user_id), + errorType = error_types::DEVICE_LIST_DB_LOG, + "User has missing or empty device list!" + ); + return Err( + tonic::Status::failed_precondition( + tonic_status_messages::NO_DEVICE_LIST, + ) + .into(), + ); + }; + + if last_update.current_primary_signature.is_none() { + return Ok(UserLoginFlow::V1Flow); + } + + if history.len() == 1 { + let user_identifier = self + .get_user_identity(user_id) + .await? + .ok_or_else(|| { + tonic::Status::not_found(tonic_status_messages::USER_NOT_FOUND) + })? + .identifier; + return match crate::comm_service::backup::user_has_backup( + user_identifier.username(), + ) + .await + { + Ok(true) => Ok(UserLoginFlow::SignedDeviceListFlow), + Ok(false) => Ok(UserLoginFlow::V1Flow), + Err(err) => Err(err), + }; + } + + Ok(UserLoginFlow::SignedDeviceListFlow) + } + } + #[tracing::instrument(skip_all)] pub(super) fn reorder_device_list( user_id: &str,