finger: provide server with more arguments
This commit is contained in:
+44
-2
@@ -1,7 +1,10 @@
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clap::{CommandFactory, Parser, builder::ArgPredicate};
|
use clap::{CommandFactory, Parser, builder::ArgPredicate};
|
||||||
use clap_complete::{Shell, generate};
|
use clap_complete::{Shell, generate};
|
||||||
use roowho2_lib::server::varlink_api::VarlinkFingerClientProxy;
|
use roowho2_lib::server::{
|
||||||
|
fingerd::{FingerRequestInfo, FingerRequestNetworking},
|
||||||
|
varlink_api::VarlinkFingerClientProxy,
|
||||||
|
};
|
||||||
|
|
||||||
/// User information lookup program
|
/// User information lookup program
|
||||||
///
|
///
|
||||||
@@ -122,6 +125,32 @@ pub struct Args {
|
|||||||
users: Option<Vec<String>>,
|
users: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn determine_request_info(args: &Args) -> FingerRequestInfo {
|
||||||
|
if args.long {
|
||||||
|
FingerRequestInfo::Long {
|
||||||
|
prevent_files: args.prevent_files,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug_assert!(
|
||||||
|
args.short,
|
||||||
|
"Either short or long output format must be selected"
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
!args.host || !args.office,
|
||||||
|
"Host and office options cannot both be enabled for short output format"
|
||||||
|
);
|
||||||
|
if args.host {
|
||||||
|
FingerRequestInfo::ShortHost {
|
||||||
|
restrict_gecos: args.gecos,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FingerRequestInfo::ShortOffice {
|
||||||
|
restrict_gecos: args.gecos,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
@@ -140,8 +169,21 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.await
|
.await
|
||||||
.expect("Failed to connect to fingerd server");
|
.expect("Failed to connect to fingerd server");
|
||||||
|
|
||||||
|
let request_info = determine_request_info(&args);
|
||||||
|
let request_networking = match (args.ipv4, args.ipv6) {
|
||||||
|
(true, false) => FingerRequestNetworking::IPv4Only,
|
||||||
|
(false, true) => FingerRequestNetworking::IPv6Only,
|
||||||
|
_ => FingerRequestNetworking::Any,
|
||||||
|
};
|
||||||
|
|
||||||
let reply = conn
|
let reply = conn
|
||||||
.finger(args.users)
|
.finger(
|
||||||
|
args.users,
|
||||||
|
!args.no_name_match,
|
||||||
|
request_info,
|
||||||
|
request_networking,
|
||||||
|
args.no_acct,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.context("Failed to send finger request")?
|
.context("Failed to send finger request")?
|
||||||
.map_err(|e| anyhow::anyhow!("Server returned an error for finger request: {:?}", e))?;
|
.map_err(|e| anyhow::anyhow!("Server returned an error for finger request: {:?}", e))?;
|
||||||
|
|||||||
+24
-2
@@ -6,15 +6,37 @@ use std::{
|
|||||||
|
|
||||||
use chrono::{DateTime, Duration, Timelike, Utc};
|
use chrono::{DateTime, Duration, Timelike, Utc};
|
||||||
use nix::sys::stat::stat;
|
use nix::sys::stat::stat;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use users::all_users;
|
use users::all_users;
|
||||||
use uucore::utmpx::Utmpx;
|
use uucore::utmpx::Utmpx;
|
||||||
|
|
||||||
use crate::proto::finger_protocol::{FingerResponseUserEntry, FingerResponseUserSession};
|
use crate::proto::finger_protocol::{FingerResponseUserEntry, FingerResponseUserSession};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum FingerRequestNetworking {
|
||||||
|
Any,
|
||||||
|
IPv4Only,
|
||||||
|
IPv6Only,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum FingerRequestInfo {
|
||||||
|
ShortHost {
|
||||||
|
restrict_gecos: bool,
|
||||||
|
},
|
||||||
|
ShortOffice {
|
||||||
|
restrict_gecos: bool,
|
||||||
|
},
|
||||||
|
Long {
|
||||||
|
prevent_files: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
/// Search for users whose username or full name contains the search string.
|
/// Search for users whose username or full name contains the search string.
|
||||||
pub fn search_for_user(
|
pub fn search_for_user(
|
||||||
search_string: &str,
|
search_string: &str,
|
||||||
dont_search_fullnames: bool,
|
match_fullnames: bool,
|
||||||
|
_request_info: &FingerRequestInfo,
|
||||||
) -> Vec<anyhow::Result<FingerResponseUserEntry>> {
|
) -> Vec<anyhow::Result<FingerResponseUserEntry>> {
|
||||||
(unsafe { all_users() })
|
(unsafe { all_users() })
|
||||||
.filter_map(|user| {
|
.filter_map(|user| {
|
||||||
@@ -42,7 +64,7 @@ pub fn search_for_user(
|
|||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let matches_username = username.contains(search_string);
|
let matches_username = username.contains(search_string);
|
||||||
let matches_fullname = !dont_search_fullnames && full_name.contains(search_string);
|
let matches_fullname = match_fullnames && full_name.contains(search_string);
|
||||||
if matches_username || matches_fullname {
|
if matches_username || matches_fullname {
|
||||||
match get_local_user(&username) {
|
match get_local_user(&username) {
|
||||||
Ok(Some(user_entry)) => Some(Ok(user_entry)),
|
Ok(Some(user_entry)) => Some(Ok(user_entry)),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use zlink::{ReplyError, service::MethodReply};
|
|||||||
use crate::{
|
use crate::{
|
||||||
proto::{WhodStatusUpdate, WhodUserEntry, finger_protocol::FingerResponseUserEntry},
|
proto::{WhodStatusUpdate, WhodUserEntry, finger_protocol::FingerResponseUserEntry},
|
||||||
server::{
|
server::{
|
||||||
fingerd::{self},
|
fingerd::{self, FingerRequestInfo, FingerRequestNetworking},
|
||||||
rwhod::RwhodStatusStore,
|
rwhod::RwhodStatusStore,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -62,6 +62,10 @@ pub trait VarlinkFingerClientProxy {
|
|||||||
async fn finger(
|
async fn finger(
|
||||||
&mut self,
|
&mut self,
|
||||||
user_queries: Option<Vec<String>>,
|
user_queries: Option<Vec<String>>,
|
||||||
|
match_fullnames: bool,
|
||||||
|
request_info: FingerRequestInfo,
|
||||||
|
request_networking: FingerRequestNetworking,
|
||||||
|
disable_user_account_db: bool,
|
||||||
) -> zlink::Result<Result<VarlinkFingerResponse, VarlinkFingerClientError>>;
|
) -> zlink::Result<Result<VarlinkFingerResponse, VarlinkFingerClientError>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +73,13 @@ pub trait VarlinkFingerClientProxy {
|
|||||||
#[serde(tag = "method", content = "parameters")]
|
#[serde(tag = "method", content = "parameters")]
|
||||||
pub enum VarlinkFingerClientRequest {
|
pub enum VarlinkFingerClientRequest {
|
||||||
#[serde(rename = "no.ntnu.pvv.roowho2.finger.Finger")]
|
#[serde(rename = "no.ntnu.pvv.roowho2.finger.Finger")]
|
||||||
Finger { user_queries: Option<Vec<String>> },
|
Finger {
|
||||||
|
user_queries: Option<Vec<String>>,
|
||||||
|
match_fullnames: bool,
|
||||||
|
request_info: FingerRequestInfo,
|
||||||
|
request_networking: FingerRequestNetworking,
|
||||||
|
disable_user_account_db: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@@ -150,13 +160,17 @@ impl VarlinkRoowhoo2ClientServer {
|
|||||||
async fn handle_finger_request(
|
async fn handle_finger_request(
|
||||||
&self,
|
&self,
|
||||||
user_queries: Option<Vec<String>>,
|
user_queries: Option<Vec<String>>,
|
||||||
|
match_fullnames: bool,
|
||||||
|
request_info: FingerRequestInfo,
|
||||||
|
_request_networking: FingerRequestNetworking,
|
||||||
|
_disable_user_account_db: bool,
|
||||||
) -> VarlinkFingerResponse {
|
) -> VarlinkFingerResponse {
|
||||||
match user_queries {
|
match user_queries {
|
||||||
// TODO: deduplicate results
|
// TODO: deduplicate results
|
||||||
Some(usernames) => usernames
|
Some(usernames) => usernames
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map::<Vec<_>, _>(|username| {
|
.flat_map::<Vec<_>, _>(|username| {
|
||||||
fingerd::search_for_user(&username, false)
|
fingerd::search_for_user(&username, match_fullnames, &request_info)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|res| (username.clone(), res))
|
.map(|res| (username.clone(), res))
|
||||||
.collect()
|
.collect()
|
||||||
@@ -211,10 +225,23 @@ impl zlink::Service<zlink::unix::Stream> for VarlinkRoowhoo2ClientServer {
|
|||||||
))),
|
))),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
),
|
),
|
||||||
VarlinkMethod::Finger(VarlinkFingerClientRequest::Finger { user_queries }) => (
|
VarlinkMethod::Finger(VarlinkFingerClientRequest::Finger {
|
||||||
|
user_queries,
|
||||||
|
match_fullnames,
|
||||||
|
request_info,
|
||||||
|
request_networking,
|
||||||
|
disable_user_account_db,
|
||||||
|
}) => (
|
||||||
MethodReply::Single(Some(VarlinkReply::Finger(
|
MethodReply::Single(Some(VarlinkReply::Finger(
|
||||||
VarlinkFingerClientResponse::Finger(
|
VarlinkFingerClientResponse::Finger(
|
||||||
self.handle_finger_request(user_queries.clone()).await,
|
self.handle_finger_request(
|
||||||
|
user_queries.clone(),
|
||||||
|
*match_fullnames,
|
||||||
|
request_info.clone(),
|
||||||
|
request_networking.clone(),
|
||||||
|
*disable_user_account_db,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
),
|
),
|
||||||
))),
|
))),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
|||||||
Reference in New Issue
Block a user