1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#![cfg_attr(not(debug_assertions), allow(dead_code, unused_imports, unused_variables))]
use url::Url;
use ate::prelude::*;
use std::io::Write;
use std::io::stdout;

mod model;
mod helper;

pub use crate::model::*;
pub use helper::chain_url;
pub use helper::conf_auth;
pub use helper::password_to_read_key;

pub async fn main_login(
    username: Option<String>,
    password: Option<String>,
    code: Option<String>,
    auth: Url
) -> Result<AteSession, AteError>
{
    let username = match username {
        Some(a) => a,
        None => {
            print!("Username: ");
            stdout().lock().flush()?;
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).expect("Did not enter a valid username");
            s
        }
    };

    let password = match password {
        Some(a) => a,
        None => {
            print!("Password: ");
            stdout().lock().flush()?;
            rpassword::read_password().unwrap()
        }
    };

    // Compute the read and write keys
    let read_key = password_to_read_key(&username, &password, 1000);

    let _code = match code {
        Some(a) => a,
        None => {
            print!("Code: ");
            stdout().lock().flush()?;
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).expect("Did not enter a valid username");
            s
        }
    };

    // Load the user credentials
    load_credentials(username, read_key, auth).await
}

pub async fn load_credentials(username: String, read_key: EncryptKey, auth: Url) -> Result<AteSession, AteError>
{
    let mut conf = ConfAte::default();
    conf.configured_for(ConfiguredFor::BestSecurity);
    conf.wire_format = SerializationFormat::Json;
    
    // Prepare for the load operation
    let key = PrimaryKey::from(username.clone());
    let mut session = AteSession::new(&conf);
    session.add_read_key(&read_key);

    // Compute which chain our user exists in
    let chain_url = crate::helper::chain_url(auth, &username);

    // Generate a chain key that matches this username on the authentication server
    let registry = ate::mesh::Registry::new(&conf).await;
    let chain = registry.open(&chain_url).await?;

    // Attempt to save a user
    let mut dio = chain.dio_ext(&session, TransactionScope::Full).await;
    let _ = dio.store(User {
        person: DaoRef::default(),
        account: DaoRef::default(),
        role: UserRole::Human,
        status: UserStatus::Unverified,
        not_lockable: false,
        failed_logins: 0,
        last_login: None,
        login_methods: Vec::new(),
        access: Vec::new(),
        foreign: DaoForeign::default(),
    })?;
    dio.commit().await?;

    // Load the user
    let mut dio = chain.dio(&session).await;
    let user = dio.load::<User>(&key).await?;

    // Build a new session
    let mut session = AteSession::new(&conf);
    for access in user.access.iter() {
        if let Some(read) = &access.read {
            session.add_read_key(read);
        }
        if let Some(write) = &access.write {
            session.add_write_key(write);
        }
    }
    Ok(session)
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}