use serde::{Deserialize, Serialize}; use std::fmt; use std::time::SystemTime; use strum::Display; #[cfg(feature = "server")] mod server { pub use crate::models::schema::*; pub use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; pub use diesel_derive_enum::DbEnum; } #[cfg(feature = "server")] use self::server::*; use crate::{ config::get_self_id, conv::systime_to_string, jobs::NamedJobBatch, platform, types::Id, u_runner::ExecResult, }; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Display)] #[cfg_attr( feature = "server", derive(DbEnum), ExistingTypePath = "sql_types::Agentstate" )] pub enum AgentState { New, Active, Banned, } //belongs_to #[derive(Clone, Serialize, Deserialize, PartialEq)] #[cfg_attr( feature = "server", derive(Identifiable, Queryable, Insertable, AsChangeset), diesel(table_name = agents) )] pub struct Agent { pub alias: Option, pub hostname: String, pub host_info: String, pub id: Id, pub ip_gray: Option, pub ip_white: Option, pub is_root: bool, pub is_root_allowed: bool, pub last_active: SystemTime, pub platform: String, pub regtime: SystemTime, pub state: AgentState, pub token: Option, pub username: String, } impl Agent { pub fn empty() -> Self { Self { alias: None, id: get_self_id(), hostname: String::new(), host_info: String::new(), is_root: false, is_root_allowed: false, last_active: SystemTime::now(), platform: String::new(), regtime: SystemTime::now(), state: AgentState::New, token: None, username: String::new(), ip_gray: None, ip_white: None, } } pub fn with_current_platform() -> Self { Self { platform: platform::current_as_string(), ..Self::empty() } } pub fn touch(&mut self) { self.last_active = SystemTime::now(); } pub async fn gather() -> Self { #[cfg(unix)] let cmds = vec![ ("hostname", "uname -a"), ("host_info", "hostnamectl --json=pretty"), ("is_root", "id -u"), ("username", "id -un"), ]; #[cfg(windows)] let cmds = vec![ ("hostname", "uname -a"), ("host_info", "hostnamectl --json=pretty"), ("is_root", "id -u"), ("username", "id -un"), ]; let mut builder = NamedJobBatch::from_shell(cmds).unwrap_one().wait().await; let decoder = |job_result: ExecResult| job_result.unwrap().to_str_result().trim().to_string(); Self { hostname: decoder(builder.pop("hostname")), host_info: decoder(builder.pop("host_info")), is_root: &decoder(builder.pop("is_root")) == "0", username: decoder(builder.pop("username")), ..Self::with_current_platform() } } } impl fmt::Debug for Agent { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Agent") .field("alias", &self.alias) .field("hostname", &self.hostname) .field("host_info", &self.host_info) .field("id", &self.id.to_string()) .field("ip_gray", &self.ip_gray) .field("ip_white", &self.ip_white) .field("is_root", &self.is_root) .field("is_root_allowed", &self.is_root_allowed) .field("last_active", &systime_to_string(self.last_active)) .field("platform", &self.platform) .field("regtime", &systime_to_string(self.regtime)) .field("state", &self.state) .field("token", &self.token) .field("username", &self.username) .finish() } }