fingerd: add raw user response variant
Build and test / check (push) Successful in 1m34s
Build and test / build (push) Successful in 1m41s
Build and test / test (push) Successful in 2m4s
Build and test / docs (push) Successful in 3m19s

This commit is contained in:
2026-04-29 06:22:20 +09:00
parent 02279a9225
commit be07298867
3 changed files with 52 additions and 28 deletions
+43 -23
View File
@@ -214,7 +214,13 @@ fn parse_bsd_finger_time(time: &str) -> anyhow::Result<DateTime<Utc>> {
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FingerResponseUserEntry {
pub enum FingerResponseUserEntry {
Structured(Box<FingerResponseStructuredUserEntry>),
Raw(String),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FingerResponseStructuredUserEntry {
/// The unix username of this user, as noted in passwd
pub username: String,
@@ -258,7 +264,7 @@ pub struct FingerResponseUserEntry {
pub plan: Option<String>,
}
impl FingerResponseUserEntry {
impl FingerResponseStructuredUserEntry {
#[allow(clippy::too_many_arguments)]
pub fn new(
username: String,
@@ -736,9 +742,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "alice".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"alice".to_string(),
)
.unwrap();
assert_eq!(user_entry.username, "alice");
assert_eq!(user_entry.full_name, "Alice Wonderland");
assert_eq!(user_entry.home_dir, PathBuf::from("/home/alice"));
@@ -762,9 +770,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "alice".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"alice".to_string(),
)
.unwrap();
assert_eq!(user_entry.office, Some("123 Main St".to_string()));
assert_eq!(user_entry.office_phone, Some("012-345-6789".to_string()));
@@ -786,9 +796,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "alice".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"alice".to_string(),
)
.unwrap();
assert_eq!(user_entry.office, Some("123 Main St".to_string()));
assert_eq!(user_entry.office_phone, Some("012-345-6789".to_string()));
@@ -807,9 +819,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"bob".to_string(),
)
.unwrap();
assert!(user_entry.never_logged_in);
assert!(user_entry.sessions.is_empty());
@@ -827,9 +841,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"bob".to_string(),
)
.unwrap();
assert_eq!(user_entry.mail_status, Some(MailStatus::NoMail));
}
@@ -846,9 +862,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"bob".to_string(),
)
.unwrap();
assert_eq!(
user_entry.mail_status,
Some(MailStatus::NewMailReceived {
@@ -870,9 +888,11 @@ mod tests {
.trim();
let response = RawFingerResponse::from(response_content.to_string());
let user_entry =
FingerResponseUserEntry::try_from_raw_finger_response(&response, "bob".to_string())
.unwrap();
let user_entry = FingerResponseStructuredUserEntry::try_from_raw_finger_response(
&response,
"bob".to_string(),
)
.unwrap();
assert_eq!(
user_entry.mail_status,
Some(MailStatus::MailLastRead(
+5 -5
View File
@@ -11,7 +11,7 @@ use users::all_users;
use uucore::utmpx::{Utmpx, UtmpxRecord};
use crate::{
proto::finger_protocol::{FingerResponseUserEntry, FingerResponseUserSession},
proto::finger_protocol::{FingerResponseStructuredUserEntry, FingerResponseUserSession},
server::fingerd::{FingerRequestInfo, local_email},
};
@@ -20,7 +20,7 @@ pub fn search_for_user(
search_string: &str,
match_fullnames: bool,
_request_info: &FingerRequestInfo,
) -> Vec<anyhow::Result<FingerResponseUserEntry>> {
) -> Vec<anyhow::Result<FingerResponseStructuredUserEntry>> {
(unsafe { all_users() })
.filter_map(|user| {
let user = match nix::unistd::User::from_uid(user.uid().into()) {
@@ -69,7 +69,7 @@ pub fn search_for_user(
/// Retrieve information about all users currently logged in, based on utmpx records.
pub fn finger_utmp_users(
_request_info: &FingerRequestInfo,
) -> Vec<anyhow::Result<FingerResponseUserEntry>> {
) -> Vec<anyhow::Result<FingerResponseStructuredUserEntry>> {
Utmpx::iter_all_records()
.filter(|entry| entry.is_user_process())
.into_group_map_by(|entry| entry.user())
@@ -113,7 +113,7 @@ fn read_file_content_if_exists(path: &Path) -> anyhow::Result<Option<String>> {
fn get_local_user(
username: &str,
utmp_records: Option<Vec<UtmpxRecord>>,
) -> anyhow::Result<Option<FingerResponseUserEntry>> {
) -> anyhow::Result<Option<FingerResponseStructuredUserEntry>> {
tracing::trace!(
"Retrieving local user information for username: {}",
username
@@ -211,7 +211,7 @@ fn get_local_user(
let plan_path = user_entry.dir.join(".plan");
let plan = read_file_content_if_exists(&plan_path)?;
Ok(Some(FingerResponseUserEntry::new(
Ok(Some(FingerResponseStructuredUserEntry::new(
username,
full_name,
home_dir,
+4
View File
@@ -204,6 +204,8 @@ impl VarlinkRoowhoo2ClientServer {
None
}
})
.map(Box::new)
.map(FingerResponseUserEntry::Structured)
.collect(),
None => finger_utmp_users(&request_info)
.into_iter()
@@ -214,6 +216,8 @@ impl VarlinkRoowhoo2ClientServer {
None
}
})
.map(Box::new)
.map(FingerResponseUserEntry::Structured)
.collect(),
}
}