Files
spacedrive/core/src/api/libraries.rs
jake d1b6263ae7 [ENG-355] Keychain integration (and some typesafety) (#558)
* update crypto MSRV

* rename `keychain` to `keyring`

* make a start on the keymanager unlock refactor/keychain integration

* update routes

* update bindings

* add const identifiers

* add UI/front-end support for unlocking KM with OS keychains

* remove SK from lib creation dialog

* update query name

* add keyring functions

* attempt to update `change_master_password()` to use the keychain

* cleanup, fix master password change ui, better secret key in keyring detection

* cleanup TS a little

* add route for getting secret key from keyring

* update bindings

* update var names + show secret key in keys settings

* add `react-qr-code` and option to view the secret key (if it's in the OS keyring)

* allow copying SK to clipboard

* add `key_type` so we're not reliant on specific UUIDs for root/verification key handling

* clippy

* fix mobile typecheck

* fix typecheck, fix typo and tweak balloon hash parameters

* minor cleanup + typo fix

* use newtype structs

* WIP type refactoring (major readability boost!)

* update `use`

* add tokio `sync` feature

* too many structs? idk

* more cleanup

* add `generate` and `Nonce`

* `Nonce` and `Key` typesafety (beautiful)

* clippy + cleanup

* update code & examples

* fix bug & remove `ProtectedVec` as it looked out of place

* use `Key`

* add a query invalidation to make the UI extremely responsive

* ci pls work

* remove `keyringHasSk` route
2023-02-07 12:03:12 +00:00

124 lines
3.2 KiB
Rust

use crate::{
library::LibraryConfig,
prisma::statistics,
volume::{get_volumes, save_volume},
};
use super::{utils::LibraryRequest, RouterBuilder};
use chrono::Utc;
use fs_extra::dir::get_size; // TODO: Remove this dependency as it is sync instead of async
use rspc::Type;
use sd_crypto::{
crypto::stream::Algorithm, keys::hashing::HashingAlgorithm,
primitives::types::OnboardingConfig, Protected,
};
use serde::Deserialize;
use tokio::fs;
use uuid::Uuid;
pub(crate) fn mount() -> RouterBuilder {
<RouterBuilder>::new()
.query("list", |t| {
t(|ctx, _: ()| async move { ctx.library_manager.get_all_libraries_config().await })
})
.library_query("getStatistics", |t| {
t(|_, _: (), library| async move {
let _statistics = library
.db
.statistics()
.find_unique(statistics::id::equals(library.node_local_id))
.exec()
.await?;
// TODO: get from database, not sys
let volumes = get_volumes();
save_volume(&library).await?;
let mut available_capacity: u64 = 0;
let mut total_capacity: u64 = 0;
if volumes.is_ok() {
for volume in volumes? {
total_capacity += volume.total_capacity;
available_capacity += volume.available_capacity;
}
}
let library_db_size = match fs::metadata(library.config().data_directory()).await {
Ok(metadata) => metadata.len(),
Err(_) => 0,
};
let thumbnail_folder_size =
get_size(library.config().data_directory().join("thumbnails"));
use statistics::*;
let params = vec![
id::set(1), // Each library is a database so only one of these ever exists
date_captured::set(Utc::now().into()),
total_object_count::set(0),
library_db_size::set(library_db_size.to_string()),
total_bytes_used::set(0.to_string()),
total_bytes_capacity::set(total_capacity.to_string()),
total_unique_bytes::set(0.to_string()),
total_bytes_free::set(available_capacity.to_string()),
preview_media_bytes::set(thumbnail_folder_size.unwrap_or(0).to_string()),
];
Ok(library
.db
.statistics()
.upsert(
statistics::id::equals(1), // Each library is a database so only one of these ever exists
params.clone(),
params,
)
.exec()
.await?)
})
})
.mutation("create", |t| {
#[derive(Deserialize, Type)]
pub struct CreateLibraryArgs {
name: String,
password: Protected<String>,
algorithm: Algorithm,
hashing_algorithm: HashingAlgorithm,
}
t(|ctx, args: CreateLibraryArgs| async move {
Ok(ctx
.library_manager
.create(
LibraryConfig {
name: args.name.to_string(),
..Default::default()
},
OnboardingConfig {
password: args.password,
algorithm: args.algorithm,
hashing_algorithm: args.hashing_algorithm,
},
)
.await?)
})
})
.mutation("edit", |t| {
#[derive(Type, Deserialize)]
pub struct EditLibraryArgs {
pub id: Uuid,
pub name: Option<String>,
pub description: Option<String>,
}
t(|ctx, args: EditLibraryArgs| async move {
Ok(ctx
.library_manager
.edit(args.id, args.name, args.description)
.await?)
})
})
.mutation("delete", |t| {
t(|ctx, id: Uuid| async move { Ok(ctx.library_manager.delete_library(id).await?) })
})
}