Init
This commit is contained in:
commit
2ba4c3b1c2
10 changed files with 556 additions and 0 deletions
8
src/symbols/mod.rs
Normal file
8
src/symbols/mod.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
pub trait Symbol {
|
||||
type Error;
|
||||
fn target_reached(&self) -> Result<bool, Self::Error>;
|
||||
fn execute(&self) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
pub mod user;
|
||||
pub mod systemd;
|
||||
1
src/symbols/systemd/mod.rs
Normal file
1
src/symbols/systemd/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod user_session;
|
||||
67
src/symbols/systemd/user_session.rs
Normal file
67
src/symbols/systemd/user_session.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::io::Error as IoError;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use command_runner::CommandRunner;
|
||||
use symbols::Symbol;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SystemdUserSessionError<E: Error> {
|
||||
ExecError(E)
|
||||
}
|
||||
|
||||
impl<E: Error> Error for SystemdUserSessionError<E> {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
&SystemdUserSessionError::ExecError(ref e) => e.description()
|
||||
}
|
||||
}
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
match self {
|
||||
&SystemdUserSessionError::ExecError(ref e) => Some(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Error> fmt::Display for SystemdUserSessionError<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "{}", self.description())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SystemdUserSession<'a> {
|
||||
user_name: &'a str,
|
||||
command_runner: &'a CommandRunner
|
||||
}
|
||||
|
||||
impl<'a> SystemdUserSession<'a> {
|
||||
pub fn new(user_name: &'a str, command_runner: &'a CommandRunner) -> Self {
|
||||
SystemdUserSession {
|
||||
user_name: user_name,
|
||||
command_runner: command_runner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Symbol for SystemdUserSession<'a> {
|
||||
type Error = SystemdUserSessionError<IoError>;
|
||||
fn target_reached(&self) -> Result<bool, Self::Error> {
|
||||
let mut path = PathBuf::from("/var/lib/systemd/linger");
|
||||
path.push(self.user_name);
|
||||
Ok(path.exists())
|
||||
}
|
||||
|
||||
fn execute(&self) -> Result<(), Self::Error> {
|
||||
match self.command_runner.run_with_args("loginctl", &["enable-linger", self.user_name]) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(SystemdUserSessionError::ExecError(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for SystemdUserSession<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{
|
||||
write!(f, "Systemd user session for {}", self.user_name)
|
||||
}
|
||||
}
|
||||
187
src/symbols/user.rs
Normal file
187
src/symbols/user.rs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::io::Error as IoError;
|
||||
|
||||
use command_runner::CommandRunner;
|
||||
use symbols::Symbol;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum UserAdderError<E: Error> {
|
||||
AlreadyExists,
|
||||
UnknownError,
|
||||
ImplError(E)
|
||||
}
|
||||
|
||||
impl<E: Error> Error for UserAdderError<E> {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
&UserAdderError::AlreadyExists => "User already exists",
|
||||
&UserAdderError::UnknownError => "Unknown error",
|
||||
&UserAdderError::ImplError(_) => "User adding error"
|
||||
}
|
||||
}
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
match self {
|
||||
&UserAdderError::ImplError(ref e) => Some(e),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Error> fmt::Display for UserAdderError<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.cause() {
|
||||
Some(e) => write!(f, "{} (cause: {})", self.description(), e),
|
||||
None => write!(f, "{}", self.description())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UserAdder {
|
||||
type SubE: Error;
|
||||
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError<Self::SubE>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum UserError<E: Error> {
|
||||
GenericError,
|
||||
ExecError(E)
|
||||
}
|
||||
|
||||
impl<E: Error> Error for UserError<E> {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
&UserError::GenericError => "Could not find out if user exists",
|
||||
&UserError::ExecError(_) => "Error executing symbol"
|
||||
}
|
||||
}
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
match self {
|
||||
&UserError::ExecError(ref e) => Some(e),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Error> fmt::Display for UserError<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.cause() {
|
||||
Some(e) => write!(f, "{} (cause: {})", self.description(), e),
|
||||
None => write!(f, "{}", self.description())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct User<'a, E, A> where E: Error + Sized, A: 'a + UserAdder<SubE=E> {
|
||||
user_name: &'a str,
|
||||
command_runner: &'a CommandRunner,
|
||||
user_adder: &'a A
|
||||
}
|
||||
|
||||
impl<'a, E: Error + Sized, A: 'a + UserAdder<SubE=E>> User<'a, E, A> {
|
||||
pub fn new(user_name: &'a str, command_runner: &'a CommandRunner, user_adder: &'a A) -> User<'a, E, A> {
|
||||
User {
|
||||
user_name: user_name,
|
||||
command_runner: command_runner,
|
||||
user_adder: user_adder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Error, A: UserAdder<SubE=E>> fmt::Display for User<'a, E, A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "User {}", self.user_name)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Error, A: UserAdder<SubE=E>> Symbol for User<'a, E, A> {
|
||||
type Error = UserError<UserAdderError<E>>;
|
||||
fn target_reached(&self) -> Result<bool, Self::Error> {
|
||||
let output = self.command_runner.run_with_args("getent", &["passwd", self.user_name]);
|
||||
match output {
|
||||
Ok(output) => match output.status.code() {
|
||||
Some(2) => Ok(false),
|
||||
Some(0) => Ok(true),
|
||||
_ => Err(UserError::GenericError)
|
||||
},
|
||||
Err(_) => Err(UserError::GenericError)
|
||||
}
|
||||
}
|
||||
|
||||
fn execute(&self) -> Result<(), Self::Error> {
|
||||
self.user_adder.add_user(self.user_name).map_err(|e| UserError::ExecError(e))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SystemUserAdder<'a> {
|
||||
command_runner: &'a CommandRunner
|
||||
}
|
||||
|
||||
impl<'a> SystemUserAdder<'a> {
|
||||
pub fn new(command_runner: &'a CommandRunner) -> SystemUserAdder<'a> {
|
||||
SystemUserAdder { command_runner: command_runner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UserAdder for SystemUserAdder<'a> {
|
||||
type SubE = IoError;
|
||||
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError<IoError>> {
|
||||
let output = self.command_runner.run_with_args("adduser", &["--system", "--disabled-login", "--disabled-password", user_name]);
|
||||
match output {
|
||||
Ok(output) => match output.status.code() {
|
||||
Some(0) => Ok(()),
|
||||
Some(1) => Err(UserAdderError::AlreadyExists),
|
||||
Some(_) => Err(UserAdderError::UnknownError),
|
||||
None => Err(UserAdderError::UnknownError),
|
||||
},
|
||||
Err(e) => Err(UserAdderError::ImplError(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use command_runner::StdCommandRunner;
|
||||
use symbols::Symbol;
|
||||
use symbols::user::User;
|
||||
use symbols::user::UserAdder;
|
||||
use symbols::user::UserAdderError;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct DummyError;
|
||||
impl Error for DummyError {
|
||||
fn description(&self) -> &str {
|
||||
"DummyError"
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DummyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DummyError")
|
||||
}
|
||||
}
|
||||
|
||||
struct DummyUserAdder;
|
||||
|
||||
impl UserAdder for DummyUserAdder {
|
||||
type SubE = DummyError;
|
||||
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError<Self::SubE>> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_target_reached_nonexisting() {
|
||||
let symbol = User { user_name: "nonexisting", command_runner: &StdCommandRunner, user_adder: &DummyUserAdder };
|
||||
assert_eq!(symbol.target_reached(), Ok(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_target_reached_root() {
|
||||
let symbol = User { user_name: "root", command_runner: &StdCommandRunner, user_adder: &DummyUserAdder };
|
||||
assert_eq!(symbol.target_reached(), Ok(true));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue