use regex::Regex; use command_runner::CommandRunner; use loggers::StdErrLogger; use repository::SymbolRepository; use resources::Resource; use schema::{NonRepeatingSymbolRunner, ReportingSymbolRunner, RequirementsResolvingSymbolRunner}; use symbols::dir::Dir; use symbols::list::List; use symbols::owner::Owner; use symbols::systemd::user_session::SystemdUserSession; use symbols::tls::{TlsCsr, TlsKey}; use symbols::user::SystemUserAdder; use symbols::user::{User, UserAdder}; use symbols::{Symbol, SymbolRunner}; #[derive(Default)] pub struct Factory {} impl Factory { pub fn new() -> Self { Default::default() } pub fn get_repo<'a, CR: CommandRunner>( &self, command_runner: &'a CR, ) -> DefaultSymbolRepository<'a, SystemUserAdder<'a, CR>, CR> { DefaultSymbolRepository::new(command_runner) } pub fn get_symbol_runner<'a, RUNNER: SymbolRunner, REPO: SymbolRepository<'a>>( &self, symbol_runner: &'a RUNNER, repo: &'a REPO, ) -> Box { let runner1 = ReportingSymbolRunner::new(symbol_runner, StdErrLogger); let runner2 = NonRepeatingSymbolRunner::new(runner1); Box::new(RequirementsResolvingSymbolRunner::new(runner2, repo)) } } pub struct DefaultSymbolRepository<'a, A: 'a + UserAdder, C: 'a + CommandRunner> { user_adder: A, command_runner: &'a C, home: Regex, home_config: Regex, csr: Regex, private_key: Regex, systemd_linger: Regex, } impl<'a, C: 'a + CommandRunner> DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> { pub fn new(command_runner: &'a C) -> Self { Self { command_runner, user_adder: SystemUserAdder::new(command_runner), home: Regex::new("^/home/([^/]+)$").unwrap(), home_config: Regex::new("^/home/([^/]+)/.config(?:/|$)").unwrap(), csr: Regex::new("^/etc/ssl/local_certs/([^/]+).csr$").unwrap(), private_key: Regex::new("^/etc/ssl/private/([^/]+).key$").unwrap(), systemd_linger: Regex::new("^/var/lib/systemd/linger/([^/]+)$").unwrap(), } } } impl<'a, C: CommandRunner> SymbolRepository<'a> for DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> { fn get_symbol(&'a self, resource: &Resource) -> Option> { match resource.get_type() { "user" => Some(Box::new(User::new( resource.get_value().to_string().into(), self.command_runner, &self.user_adder, ))), "dir" => { let value = resource.get_value(); Some(if let Some(matches) = self.home_config.captures(value) { Box::new(List::new(vec![ Box::new(Dir::new(value.to_string())), Box::new(Owner::new( value.to_string(), matches[1].to_string().into(), self.command_runner, )), ])) as Box } else if let Some(matches) = self.home.captures(value) { Box::new(User::new( matches[1].to_string().into(), self.command_runner, &self.user_adder, )) as Box } else { Box::new(Dir::new(value.to_string())) as Box }) } "file" => { let value = resource.get_value(); if let Some(matches) = self.csr.captures(value) { Some(Box::new(TlsCsr::new( matches[1].to_string().into(), self.command_runner, )) as Box) } else if let Some(matches) = self.private_key.captures(value) { Some(Box::new(TlsKey::new( matches[1].to_string().into(), self.command_runner, )) as Box) } else if let Some(matches) = self.systemd_linger.captures(value) { Some(Box::new(SystemdUserSession::new( matches[1].to_string().into(), self.command_runner, )) as Box) } else { None } } _ => None, } } }