fix: Don't allow UIAA stages to be completed if no flow includes them

This commit is contained in:
Ginger
2026-03-30 13:16:18 -04:00
committed by Ellis Git
parent 0c9fa3b7e5
commit e1c54f4dec
2 changed files with 36 additions and 24 deletions
+8 -3
View File
@@ -231,7 +231,8 @@ impl Service {
if self.services.config.suspend_on_register { if self.services.config.suspend_on_register {
eprintln!( eprintln!(
"{} Accounts created after yours will be suspended, as set in your configuration.", "{} Accounts created after yours will be suspended, as set in your \
configuration.",
"Your account will not be suspended when you register.".green() "Your account will not be suspended when you register.".green()
); );
} }
@@ -239,11 +240,15 @@ impl Service {
if let Some(smtp) = &self.services.config.smtp { if let Some(smtp) = &self.services.config.smtp {
if smtp.require_email_for_registration || smtp.require_email_for_token_registration { if smtp.require_email_for_registration || smtp.require_email_for_token_registration {
eprintln!( eprintln!(
"{} Accounts created after yours may be required to provide an email address, as set in your configuration.", "{} Accounts created after yours may be required to provide an email \
address, as set in your configuration.",
"You will not be asked for your email address when you register.".yellow(), "You will not be asked for your email address when you register.".yellow(),
); );
} }
eprintln!("If you wish to associate an email address with your account, you may do so after registration in your client's settings (if supported)."); eprintln!(
"If you wish to associate an email address with your account, you may do so \
after registration in your client's settings (if supported)."
);
} }
eprintln!( eprintln!(
+28 -21
View File
@@ -226,9 +226,23 @@ impl Service {
return Ok(Err(session.get().info.clone())); return Ok(Err(session.get().info.clone()));
} }
let completed = 'completed: { let completed = {
let UiaaSession { info, identity } = session.get_mut(); let UiaaSession { info, identity } = session.get_mut();
let auth_type = auth.auth_type().expect("auth type should be set");
let flow_stages: Vec<HashSet<_>> = info
.flows
.iter()
.map(|flow| {
flow.stages
.iter()
.map(AuthType::as_str)
.map(ToOwned::to_owned)
.collect()
})
.collect();
let mut completed_stages: HashSet<_> = info let mut completed_stages: HashSet<_> = info
.completed .completed
.iter() .iter()
@@ -236,10 +250,16 @@ impl Service {
.map(ToOwned::to_owned) .map(ToOwned::to_owned)
.collect(); .collect();
// If the provided stage hasn't already been completed, check it for completion // Don't allow stages which aren't in any flows
if !completed_stages if !flow_stages
.contains(auth.auth_type().expect("auth type should be set").as_str()) .iter()
.any(|stages| stages.contains(auth_type.as_str()))
{ {
return Err!(Request(InvalidParam("No flows include the supplied stage")));
}
// If the provided stage hasn't already been completed, check it for completion
if !completed_stages.contains(auth_type.as_str()) {
match self.check_stage(auth, identity.clone()).await { match self.check_stage(auth, identity.clone()).await {
| Ok((completed_stage, updated_identity)) => { | Ok((completed_stage, updated_identity)) => {
info.auth_error = None; info.auth_error = None;
@@ -253,23 +273,10 @@ impl Service {
} }
} }
// Check all flows to see if any of them succeeded // UIAA is completed if all stages in any flow are completed
for flow in &info.flows { flow_stages
let flow_stages = flow .iter()
.stages .any(|stages| completed_stages.is_superset(stages))
.iter()
.map(AuthType::as_str)
.map(ToOwned::to_owned)
.collect();
if completed_stages.is_superset(&flow_stages) {
// All stages in this flow are completed
break 'completed true;
}
}
// No flows had all their stages completed
break 'completed false;
}; };
if completed { if completed {