#[allow(unused_imports)]
use tracing::{debug, error, info, instrument, span, trace, warn, Level};
use url::Url;
use std::io::Write;
#[cfg(unix)]
use std::env::temp_dir;
#[cfg(unix)]
use std::os::unix::fs::symlink;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use ::ate::crypto::EncryptKey;
use ::ate::prelude::*;
use crate::model::*;
pub(crate) fn compute_user_auth(user: &User) -> AteSessionUser {
let mut session = AteSessionUser::default();
for auth in user.access.iter() {
session.user.add_read_key(&auth.read);
session.user.add_private_read_key(&auth.private_read);
session.user.add_write_key(&auth.write);
}
session.user.add_uid(user.uid);
session.identity = user.email.clone();
session.broker_read = Some(user.broker_read.clone());
session.broker_write = Some(user.broker_write.clone());
session
}
pub(crate) fn compute_sudo_auth(sudo: &Sudo, session: AteSessionUser) -> AteSessionSudo {
let mut role = AteGroupRole {
purpose: AteRolePurpose::Owner,
properties: Vec::new(),
};
for auth in sudo.access.iter() {
role.add_read_key(&auth.read);
role.add_private_read_key(&auth.private_read);
role.add_write_key(&auth.write);
}
role.add_read_key(&sudo.contract_read_key);
role.add_uid(sudo.uid);
AteSessionSudo {
inner: session,
sudo: role,
}
}
pub(crate) fn complete_group_auth(
group: &Group,
inner: AteSessionInner,
) -> Result<AteSessionGroup, LoadError> {
let mut session = AteSessionGroup::new(inner, group.name.clone());
session.group.broker_read = Some(group.broker_read.clone());
session.group.broker_write = Some(group.broker_write.clone());
let mut roles = group.roles.iter().collect::<Vec<_>>();
while roles.len() > 0 {
let start = roles.len();
let mut next = Vec::new();
let shared_keys = session
.read_keys(AteSessionKeyCategory::AllKeys)
.map(|a| a.clone())
.collect::<Vec<_>>();
let super_keys = session
.private_read_keys(AteSessionKeyCategory::AllKeys)
.map(|a| a.clone())
.collect::<Vec<_>>();
for role in roles.into_iter() {
let mut added = false;
for read_key in super_keys.iter() {
if let Some(a) = role.access.unwrap(&read_key)? {
let b = session.get_or_create_group_role(&role.purpose);
b.add_read_key(&a.read);
b.add_private_read_key(&a.private_read);
b.add_write_key(&a.write);
b.add_gid(group.gid);
added = true;
break;
}
}
if added == false {
for read_key in shared_keys.iter() {
if let Some(a) = role.access.unwrap_shared(&read_key)? {
let b = session.get_or_create_group_role(&role.purpose);
b.add_read_key(&a.read);
b.add_private_read_key(&a.private_read);
b.add_write_key(&a.write);
b.add_gid(group.gid);
added = true;
break;
}
}
}
if added == false {
next.push(role);
}
}
if next.len() >= start {
break;
}
roles = next;
}
Ok(session)
}
pub async fn load_credentials(
registry: &Registry,
username: String,
read_key: EncryptKey,
_code: Option<String>,
auth: Url,
) -> Result<AteSessionUser, AteError> {
let key = PrimaryKey::from(username.clone());
let mut session = AteSessionUser::new();
session.user.add_read_key(&read_key);
let chain_key = chain_key_4hex(username.as_str(), Some("redo"));
let chain = registry.open(&auth, &chain_key).await?;
let dio = chain.dio(&session).await;
let user = dio.load::<User>(&key).await?;
let mut session = AteSessionUser::new();
for access in user.access.iter() {
session.user.add_read_key(&access.read);
session.user.add_write_key(&access.write);
}
Ok(session)
}
pub fn save_token(
token: String,
token_path: String,
) -> Result<(), AteError> {
if let Ok(old) = std::fs::canonicalize(token_path.clone()) {
let _ = std::fs::remove_file(old);
}
let _ = std::fs::remove_file(token_path.clone());
let path = std::path::Path::new(&token_path);
let _ = std::fs::create_dir_all(path.parent().unwrap().clone());
#[cfg(unix)]
let save_path = random_file();
#[cfg(not(unix))]
let save_path = token_path;
{
let path = std::path::Path::new(&save_path);
let _ = std::fs::create_dir_all(path.parent().unwrap().clone());
let mut file = std::fs::File::create(save_path.clone())?;
#[cfg(unix)]
{
let mut perms = std::fs::metadata(save_path.clone())?.permissions();
perms.set_mode(0o600);
std::fs::set_permissions(save_path.clone(), perms)?;
}
file.write_all(token.as_bytes())?;
}
#[cfg(unix)]
symlink(save_path, token_path)?;
Ok(())
}
#[cfg(unix)]
fn random_file() -> String {
let mut tmp = temp_dir();
let rnd = ate::prelude::PrimaryKey::default().as_hex_string();
let file_name = format!("{}", rnd);
tmp.push(file_name);
let tmp_str = tmp.into_os_string().into_string().unwrap();
let tmp_str = shellexpand::tilde(&tmp_str).to_string();
tmp_str
}