manager 0.1.0

Artifice Management crate
/*!
artifice manager is the crate that is responsible for managing the resources of artifice such as configs, peers list, permissions, and applications

# Examples

# Authenticate incoming user

```
use manager::{ArtificeDB, Manager};
use manager::database::Database;
use networking::peers::ArtificePeer;
use networking::ArtificeHost;
fn main(){
    let database = ArtificeDB::default();
    let manager = Manager::load(database, b"example_password").unwrap();
    let host = ArtificeHost::from_host_data(manager.config()).unwrap();
    for netstream in host {
        let stream = netstream.unwrap();
        if manager.authenticate(stream.peer()).unwrap() {
            println!("peer authenticated");
        }
    }
}
 ```

# Connect to remote peer
```
use manager::{ArtificeDB, Manager};
use manager::database::Database;
use networking::peers::ArtificePeer;
use networking::ArtificeHost;

fn main(){
    let database = ArtificeDB::default();
    let manager = Manager::load(database, b"example_password").unwrap();
    let host = ArtificeHost::from_host_data(manager.config()).unwrap();
    let peer = manager.get_peer("global_peer_hash").unwrap();
    let host = ArtificeHost::from_host_data(manager.config()).unwrap();
    let stream = host.connect(peer).unwrap();
}
```
*/
#![feature(maybe_uninit_ref)]
#[macro_use]
extern crate serde_derive;
/// provides Table, and Database traits
pub mod database;
pub use database::*;
/// permissions management implementation
/// may transfer to seperate crate
pub mod permissions;
/// used to archive and compress configs
pub mod archive;
/// will be used for users tracking when a secure implementation is created
pub mod users;
pub use crate::database::*;
use crate::permissions::*;
use networking::encryption::*;
use networking::query::Query;
use networking::ArtificeConfig;
use networking::ArtificePeer;
use serde::{de::Deserialize, de::DeserializeOwned,ser::Serialize};
use crate::archive::*;
use std::{
    convert::AsRef,
    fmt::Debug,
    path::{Path, PathBuf},
    fs::File,
    io::{Read},
};

#[derive(Debug, Clone)]
pub struct PermissionManager {
    permissions: PermissionsGranted,
    password: Vec<u8>,
    query: Query<(Permission, ArtificePeer), PermissionResult>,
}
impl PermissionManager {
    pub fn get_query(&self) -> Query<(Permission, ArtificePeer), PermissionResult>{
        self.query.clone()
    }
}
impl<'a> Table<'a, String, Permission, std::io::Error> for PermissionManager{

    fn create<P: AsRef<Path>>(path: P, pass: &[u8]) -> Result<Self, std::io::Error>{
        let mut password = Vec::new();
        password.extend_from_slice(pass);
        let query = Query::new();
        let mut file = File::open(&format!("{}.artusr",path.as_ref().display()))?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        let mut outbuf = Vec::new();
        decrypt(pass, &data, &mut outbuf);
        let permissions = serde_json::from_str(&String::from_utf8(outbuf).unwrap()).unwrap();
        Ok(Self{permissions, password, query})
    }
    fn get<K: ToString>(&self, key: &K) -> Result<Permission, std::io::Error>{
        for permission in self.permissions.iter(){
            if key.to_string() == permission.get_key(){
                return Ok(permission.clone())
            }
        }
        Err(std::io::Error::new(std::io::ErrorKind::NotFound, "permission not found"))
    }
    fn insert<K: ToString>(&self, _permission: &Permission) -> Result<(), std::io::Error>{
        Ok(())
    }
}
/// this is the primary database containing information on the artifice installation
/// it provides access to a list of applications, and there granted permissions
/// as well as configuraiton for networking, and a table of peers to connect to
///
///    creating database from custom location
///    
///    # Example
///    // basic example
///    ```
///    let database = ArtificeDB::create("/home/user/.artifice/");
///    let permissions_entry = database.load_entry("permissions", b"password");
///    // this will create the permissionsgranted object which is a vector of permission 
///    let permissions = permissions_entry.unwrap();
///    
///    or
///
///    let archive = database.archive();
///   ```
/// 
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArtificeDB {
    root: String,
    entries: Vec<String>,
}

impl ArtificeDB {
    pub fn default_from_root<P: AsRef<Path>>(root: P) -> Self {
        let root = format!("{}", root.as_ref().display());
        let permissions = format!("{}permissions.artusr", root);
        let peers = format!("{}peers/", root);
        let config = format!("{}config.artusr", root);
        let applications = format!("{}applications.artusr", root);
        let mut entries = Vec::new();
        entries.push(permissions);
        entries.push(peers);
        entries.push(config);
        entries.push(applications);
        Self {
            root,
            entries,
        }
    }
    pub fn archive(&self) -> std::io::Result<Vec<u8>>{
        archive(&self.root)
    }
    pub fn install_archive(&self, archive: &[u8]) -> std::io::Result<()>{
        dearchive(archive, &self.root)
    }
}
impl Database<std::io::Error> for ArtificeDB {
    fn create<P: AsRef<Path>>(root: P) -> Result<Self, std::io::Error> {
        Ok(Self::default_from_root(root))
    }
    fn root(&self) -> PathBuf {
        let path = Path::new(&self.root);
        path.to_path_buf()
    }
    fn create_table<'a, B, A, T>(&self, key: B, password: &[u8]) -> Result<T, std::io::Error>
    where
        B: ToString,
        A: Debug + Clone + Serialize + Deserialize<'a> + GetPrimaryKey<B>,
        T: Table<'a, B, A, std::io::Error>,
    {
        let pathstr = format!("{}{}", self.root, key.to_string());
        let path = Path::new(&pathstr);
        T::create(path, password)
    }
    fn load_entry<K, T>(&self, key: K, password: &[u8]) -> Result<T, std::io::Error>
    where
        K: ToString,
        T: Debug + Clone + Serialize + DeserializeOwned,
    {
        let pathstr = format!("{}{}", self.root, key.to_string());
        let path = Path::new(&pathstr);
        let mut file = File::open(path)?;
        let mut invec = Vec::new();
        let mut outvec = Vec::new();
        file.read_to_end(&mut invec)?;
        decrypt(password, &invec, &mut outvec);
        let content = String::from_utf8(outvec).unwrap();
        let entry = serde_json::from_value(serde_json::Value::String(content)).unwrap();
        Ok(entry)
    }
}
impl Default for ArtificeDB {
    fn default() -> Self {
        let root = format!(
            "{}.artifice/",
            dirs::home_dir().unwrap().display().to_string()
        );
        Self::default_from_root(root)
    }
}
/// this is the main management structure that other structures work through
///
/// # Example
///
/// ```
/// use networking::{ArtificeHost};
///
/// let database = ArtificeDB::default();
/// let manager = Manager::load(database, b"example_password").unwrap();
/// let host = ArtificeHost::from_host_data(manager.config());
/// for networkstream in host {
///     // do something with the peer
/// }
/// 
/// ```
///
pub struct Manager {
    _permissions: PermissionManager,
    _database: ArtificeDB,
    peers: ArtificePeers,
    config: ArtificeConfig,
}
impl Manager{
    /// loads the configuration for artifice from its respective files in the database
    ///
    /// # Arguments
    /// 
    /// database: the database to load,
    /// password: decryption key used to read and write files
    ///  
    /// # Example
    ///
    /// use manager::{ArtificeDB, Manager};
    /// use manager::database::Database;
    /// use networking::peers::ArtificePeer;
    /// use networking::ArtificeHost;
    /// fn main(){
    ///     let database = ArtificeDB::default();
    ///     let manager = Manager::load(database, b"example password").unwrap();
    ///     let host = ArtificeHost::from_host_data(manager.config()).unwrap();
    ///     for netstream in host {
    ///         let stream = netstream.unwrap();
    ///         if manager.authenticate(stream.peer()).unwrap() {
    ///             println!("peer authenticated");
    ///         }
    ///     }
    /// }
    ///
    pub fn load(database: ArtificeDB, password: &[u8]) -> Result<Self, std::io::Error>{
        let permissions = database.create_table("permissions".to_string(), password)?;
        let peers = database.create_table("peers/".to_string(), password)?;
        let config: ArtificeConfig = database.load_entry("config".to_string(), password)?;
        //let mut pass = Vec::new();
        //pass.extend_from_slice(password);
        Ok(Self {_permissions: permissions, _database: database, peers, config})
    }
    pub fn config(&self) -> &ArtificeConfig{
        &self.config
    }
    pub fn authenticate(&self, peer: &ArtificePeer) -> std::io::Result<bool>{
        Ok(self.peers.get(&peer.global_peer_hash())? == *peer)
    }
    pub fn get_peer(&self, key: &str) -> std::io::Result<ArtificePeer>{
        self.peers.get(&key.to_string())
    }
}