use regex::Regex; use std::collections::HashMap; use command_runner::CommandRunner; use command_runner::StdCommandRunner; use loggers::StdErrLogger; use repository::{DispatchingSymbolRepository, SymbolRepository}; use resources::Resource; use schema::{NonRepeatingSymbolRunner, ReportingSymbolRunner, RequirementsResolvingSymbolRunner}; use symbols::{Symbol, SymbolRunner}; use symbols::dir::Dir; use symbols::list::List; use symbols::owner::Owner; use symbols::systemd::user_session::SystemdUserSession; use symbols::tls::TlsCsr; use symbols::tls::TlsKey; use symbols::user::{User, UserAdder}; use symbols::user::SystemUserAdder; pub struct Factory { } impl Factory { pub fn new() -> Self { Self {} } 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<'a + SymbolRunner> { 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: 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 } } }