use crate::Lb;
use crate::model::api::GetPublicKeyRequest;
use crate::model::errors::{LbErr, LbResult};
use crate::model::file::{File, ShareMode};
use crate::model::file_metadata::Owner;
use crate::model::tree_like::TreeLike;
use crate::service::events::Actor;
use libsecp256k1::PublicKey;
use uuid::Uuid;
impl Lb {
#[instrument(level = "debug", skip(self))]
pub async fn share_file(&self, id: Uuid, username: &str, mode: ShareMode) -> LbResult<()> {
let account = self.get_account()?;
let username = username.to_lowercase();
let sharee = Owner(
self.client
.request(account, GetPublicKeyRequest { username: username.clone() })
.await
.map_err(LbErr::from)?
.key,
);
let mut tx = self.begin_tx().await;
let db = tx.db();
let mut tree = (&db.base_metadata)
.to_staged(&mut db.local_metadata)
.to_lazy();
db.pub_key_lookup.insert(sharee, username)?;
tree.add_share(id, sharee, mode, &self.keychain)?;
tx.end();
self.events.meta_changed(Actor::User(None));
Ok(())
}
#[instrument(level = "debug", skip(self))]
pub async fn get_pending_shares(&self) -> LbResult<Vec<File>> {
let tx = self.ro_tx().await;
let db = tx.db();
let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
let pending_roots = tree.pending_roots(&self.keychain)?.into_iter();
tree.decrypt_all(&self.keychain, pending_roots, &db.pub_key_lookup, false)
}
#[instrument(level = "debug", skip(self))]
pub async fn get_pending_share_files(&self) -> LbResult<Vec<File>> {
let tx = self.ro_tx().await;
let db = tx.db();
let mut tree = (&db.base_metadata).to_staged(&db.local_metadata).to_lazy();
let pending_files = tree.non_deleted_pending_files(&self.keychain)?.into_iter();
tree.decrypt_all(&self.keychain, pending_files, &db.pub_key_lookup, false)
}
#[instrument(level = "debug", skip(self))]
async fn delete_share(
&self, id: &Uuid, maybe_encrypted_for: Option<PublicKey>,
) -> LbResult<()> {
let mut tx = self.begin_tx().await;
let db = tx.db();
let mut tree = (&db.base_metadata)
.to_staged(&mut db.local_metadata)
.to_lazy();
tree.delete_share(id, maybe_encrypted_for, &self.keychain)?;
tx.end();
self.events.meta_changed(Actor::User(None));
Ok(())
}
#[instrument(level = "debug", skip(self))]
pub async fn known_usernames(&self) -> LbResult<Vec<String>> {
let db = self.ro_tx().await;
let db = db.db();
Ok(db
.pub_key_lookup
.iter()
.map(|(_, value)| value)
.cloned()
.collect())
}
#[instrument(level = "debug", skip(self))]
pub async fn username_exists(&self, username: &str) -> LbResult<bool> {
use crate::DEFAULT_API_LOCATION;
use crate::model::account::Account;
use crate::model::errors::LbErrKind;
let username = username.trim().to_lowercase();
if username.is_empty() {
return Ok(false);
}
if let Ok(known) = self.known_usernames().await {
if known.iter().any(|u| u.eq_ignore_ascii_case(&username)) {
return Ok(true);
}
}
let owned;
let account = match self.get_account() {
Ok(a) => a,
Err(_) => {
let api =
std::env::var("API_URL").unwrap_or_else(|_| DEFAULT_API_LOCATION.to_string());
owned = Account::new(String::new(), api);
&owned
}
};
match self
.client
.request(account, GetPublicKeyRequest { username })
.await
{
Ok(_) => Ok(true),
Err(e) => {
let err = LbErr::from(e);
match err.kind {
LbErrKind::AccountNonexistent | LbErrKind::UsernameNotFound => Ok(false),
_ => Err(err),
}
}
}
}
#[instrument(level = "debug", skip(self))]
pub async fn reject_share(&self, id: &Uuid) -> Result<(), LbErr> {
let pk = self.keychain.get_pk()?;
self.delete_share(id, Some(pk)).await
}
}