fix: address argus review on matrix admin-room reset — ascii lowercase, tighter markers, unit tests
This commit is contained in:
parent
b2913bc656
commit
97a78cc5d6
1 changed files with 56 additions and 3 deletions
|
|
@ -354,14 +354,20 @@ async fn discover_admin_room_id(
|
||||||
/// Try to parse the new password from an admin-room bot response.
|
/// Try to parse the new password from an admin-room bot response.
|
||||||
/// Conduwuit/tuwunel responds with a message like:
|
/// Conduwuit/tuwunel responds with a message like:
|
||||||
/// "Done: Password of user @user:server has been reset. The new password is: <password>"
|
/// "Done: Password of user @user:server has been reset. The new password is: <password>"
|
||||||
|
///
|
||||||
|
/// Uses [`str::to_ascii_lowercase`] for case folding — unlike `to_lowercase`,
|
||||||
|
/// ASCII lowercasing is guaranteed to produce a same-byte-length string, so the
|
||||||
|
/// byte offset from `find` is always a valid index into the original `bot_message`
|
||||||
|
/// and we never slice at a non-char boundary.
|
||||||
fn extract_new_password(bot_message: &str) -> Option<String> {
|
fn extract_new_password(bot_message: &str) -> Option<String> {
|
||||||
// Look for "new password is:" (case-insensitive) followed by whitespace + the password.
|
// ASCII lowercase: same byte length as the original, so positions from
|
||||||
let lower = bot_message.to_lowercase();
|
// `lower.find(marker)` are valid byte indices into `bot_message`.
|
||||||
|
let lower = bot_message.to_ascii_lowercase();
|
||||||
for marker in &[
|
for marker in &[
|
||||||
"new password is: ",
|
"new password is: ",
|
||||||
"new password is:",
|
"new password is:",
|
||||||
"password is: ",
|
"password is: ",
|
||||||
"password: ",
|
"password is:",
|
||||||
] {
|
] {
|
||||||
if let Some(pos) = lower.find(marker) {
|
if let Some(pos) = lower.find(marker) {
|
||||||
let rest = &bot_message[pos + marker.len()..];
|
let rest = &bot_message[pos + marker.len()..];
|
||||||
|
|
@ -378,6 +384,53 @@ fn extract_new_password(bot_message: &str) -> Option<String> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod extract_new_password_tests {
|
||||||
|
use super::extract_new_password;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuwunel_style_response() {
|
||||||
|
let msg = "Done: Password of user @atlas:pr1ma.darkest.space has been reset. The new password is: abc123XYZ!";
|
||||||
|
assert_eq!(extract_new_password(msg).as_deref(), Some("abc123XYZ!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn case_insensitive_marker() {
|
||||||
|
let msg = "Password reset complete. New Password Is: S3cr3tP@ss";
|
||||||
|
assert_eq!(extract_new_password(msg).as_deref(), Some("S3cr3tP@ss"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn marker_without_trailing_space() {
|
||||||
|
let msg = "new password is:hunter2";
|
||||||
|
assert_eq!(extract_new_password(msg).as_deref(), Some("hunter2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shorter_marker_variant() {
|
||||||
|
let msg = "Your password is: Tr0ub4dor&3";
|
||||||
|
assert_eq!(extract_new_password(msg).as_deref(), Some("Tr0ub4dor&3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_match_returns_none() {
|
||||||
|
let msg = "Command not recognised. Please try again.";
|
||||||
|
assert_eq!(extract_new_password(msg), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_after_marker_returns_none() {
|
||||||
|
let msg = "new password is: ";
|
||||||
|
assert_eq!(extract_new_password(msg), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn password_stops_at_whitespace() {
|
||||||
|
let msg = "New password is: abc123 (save it now)";
|
||||||
|
assert_eq!(extract_new_password(msg).as_deref(), Some("abc123"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reset a user's password via the Matrix admin room as a fallback for
|
/// Reset a user's password via the Matrix admin room as a fallback for
|
||||||
/// homeservers that do not implement the Synapse admin REST API (e.g.
|
/// homeservers that do not implement the Synapse admin REST API (e.g.
|
||||||
/// tuwunel 1.6.x). Sends `reset-password @<localpart>:<server>` to
|
/// tuwunel 1.6.x). Sends `reset-password @<localpart>:<server>` to
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue