roowho2_lib/server/varlink_api/
fingerd.rs1use itertools::Itertools;
2use serde::{Deserialize, Serialize};
3use zlink::ReplyError;
4
5use crate::{
6 proto::finger_protocol::FingerResponseUserEntry,
7 server::{
8 fingerd::{self, FingerRequestInfo, FingerRequestNetworking, finger_utmp_users},
9 ignore_list::IgnoreList,
10 },
11};
12
13#[zlink::proxy("no.ntnu.pvv.roowho2.finger")]
14pub trait VarlinkFingerClientProxy {
15 async fn finger(
16 &mut self,
17 user_queries: Option<Vec<String>>,
18 match_fullnames: bool,
19 request_info: FingerRequestInfo,
20 request_networking: FingerRequestNetworking,
21 disable_user_account_db: bool,
22 raw_remote_output: bool,
23 ) -> zlink::Result<Result<VarlinkFingerResponse, VarlinkFingerClientError>>;
24}
25
26#[derive(Debug, Deserialize)]
27#[serde(tag = "method", content = "parameters")]
28pub enum VarlinkFingerClientRequest {
29 #[serde(rename = "no.ntnu.pvv.roowho2.finger.Finger")]
30 Finger {
31 user_queries: Option<Vec<String>>,
32 match_fullnames: bool,
33 request_info: FingerRequestInfo,
34 request_networking: FingerRequestNetworking,
35 disable_user_account_db: bool,
36 raw_remote_output: bool,
37 },
38}
39
40#[derive(Debug, Serialize)]
41#[serde(untagged)]
42pub enum VarlinkFingerClientResponse {
43 Finger(VarlinkFingerResponse),
44}
45
46pub type VarlinkFingerResponse = Vec<FingerResponseUserEntry>;
47
48#[derive(Debug, Clone, PartialEq, ReplyError)]
49#[zlink(interface = "no.ntnu.pvv.roowho2.finger")]
50pub enum VarlinkFingerClientError {
51 InvalidRequest,
52 TimedOut,
53 Disabled,
54}
55
56pub async fn handle_finger_request(
57 finger_ignore_list: &Option<IgnoreList>,
58 user_queries: Option<Vec<String>>,
59 match_fullnames: bool,
60 request_info: FingerRequestInfo,
61 _request_networking: FingerRequestNetworking,
62 _disable_user_account_db: bool,
63 _raw_remote_output: bool,
64) -> VarlinkFingerResponse {
65 tracing::debug!(
66 user_queries = ?user_queries,
67 match_fullnames = match_fullnames,
68 request_info = ?request_info,
69 "Handling Finger request",
70 );
71 match user_queries {
72 Some(usernames) => usernames
73 .into_iter()
74 .flat_map::<Vec<_>, _>(|username| {
75 fingerd::search_for_user(
76 &username,
77 match_fullnames,
78 &request_info,
79 finger_ignore_list.as_ref(),
80 )
81 .into_iter()
82 .map(|res| (username.clone(), res))
83 .collect()
84 })
85 .dedup_by(|a, b| match (&a.1, &b.1) {
86 (Ok(user_a), Ok(user_b)) => user_a.username == user_b.username,
87 _ => false,
88 })
89 .filter_map(|(username, user)| match user {
90 Ok(user_info) => Some(user_info),
91 Err(err) => {
92 tracing::error!(
93 "Error retrieving local user information for '{}': {}",
94 username,
95 err
96 );
97 None
98 }
99 })
100 .map(Box::new)
101 .map(FingerResponseUserEntry::Structured)
102 .collect(),
103
104 None => finger_utmp_users(&request_info, finger_ignore_list.as_ref())
105 .into_iter()
106 .filter_map(|res| match res {
107 Ok(user_info) => Some(user_info),
108 Err(err) => {
109 tracing::error!("Error retrieving local user information: {}", err);
110 None
111 }
112 })
113 .map(Box::new)
114 .map(FingerResponseUserEntry::Structured)
115 .collect(),
116 }
117}