checkpoint before potentially removing seaorm

This commit is contained in:
Jamie 2021-10-01 10:23:50 -07:00
parent 0c19a92f11
commit 338b1eb0d3
11 changed files with 201 additions and 73 deletions

View file

@ -1,5 +1,5 @@
{
"name": "sd-client",
"name": "drive",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",

74
src-tauri/Cargo.lock generated
View file

@ -1201,6 +1201,18 @@ version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
version = "1.5.0"
@ -3060,6 +3072,50 @@ dependencies = [
"redox_syscall 0.2.10",
]
[[package]]
name = "refinery"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f3a3d4976479c5e9a50352cf9117896b581c939e81f4169295cb9b353d30bc8"
dependencies = [
"refinery-core",
"refinery-macros",
]
[[package]]
name = "refinery-core"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1eb7989daaee90c44763f644bfa2c3ce46b0a241b9966c1c2be9e65b4918815b"
dependencies = [
"async-trait",
"cfg-if 1.0.0",
"chrono",
"lazy_static",
"log",
"regex",
"rusqlite",
"serde",
"siphasher",
"thiserror",
"toml",
"url",
"walkdir",
]
[[package]]
name = "refinery-macros"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e2d142a0c173f7e096ae1297d677cb4bb056fc80f25f31d6b0d2a82da07beee"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"refinery-core",
"regex",
"syn 1.0.74",
]
[[package]]
name = "regex"
version = "1.5.4"
@ -3139,6 +3195,21 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "rusqlite"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57adcf67c8faaf96f3248c2a7b419a0dbc52ebe36ba83dd57fe83827c1ea4eb3"
dependencies = [
"bitflags 1.3.1",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"memchr",
"smallvec",
]
[[package]]
name = "rust-argon2"
version = "0.8.3"
@ -3260,11 +3331,14 @@ dependencies = [
"futures",
"int-enum",
"rebind",
"refinery",
"ring 0.17.0-alpha.10",
"rusqlite",
"sea-orm",
"serde",
"serde_json",
"sha256",
"sqlx",
"tauri",
"tauri-build",
]

View file

@ -25,6 +25,9 @@ crossbeam = "0.8.1"
cargo-edit = "0.8.0"
sha256 = "1.0.2"
int-enum = "0.4.0"
rusqlite = "0.25.3"
refinery = { version = "0.6.0", features = ["rusqlite"] }
sqlx = { version = "0.5.7", features = ["sqlite"] }
sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-async-std-rustls", "macros" ], default-features = false }
[features]

View file

@ -5,21 +5,21 @@ use crate::filesystem::file::File;
use tauri::InvokeError;
#[tauri::command(async)]
pub async fn read_file_command(path: &str) -> Result<File, InvokeError> {
pub async fn read_file_command(path: &str) -> Result<String, InvokeError> {
let file = file::read_file(path)
.await
.map_err(|error| InvokeError::from(format!("Failed to read file: {}", error)))?;
// file::commit_file(&file).await;
println!("file: {:?}", file);
Ok(file)
Ok("lol".to_owned())
}
#[tauri::command(async)]
pub async fn generate_buffer_checksum(path: &str) -> Result<File, InvokeError> {
let mut file = file::read_file(path)
.await
.map_err(|error| InvokeError::from(format!("Failed to read file: {}", error)))?;
// #[tauri::command(async)]
// pub async fn generate_buffer_checksum(path: &str) -> Result<File, InvokeError> {
// let mut file = file::read_file(path)
// .await
// .map_err(|error| InvokeError::from(format!("Failed to read file: {}", error)))?;
// file.buffer_checksum = Some(checksum::create_hash(&file.uri).await.unwrap());
Ok(file)
}
// // file.buffer_checksum = Some(checksum::create_hash(&file.uri).await.unwrap());
// Ok(file)
// }

View file

@ -1,21 +1,41 @@
use crate::app::config;
use crate::filesystem::file;
use sea_orm::{Database, DatabaseConnection, DbErr, Schema};
use rusqlite::Connection;
use sea_orm::{Database, DatabaseConnection, DbErr};
// use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode};
// use sqlx::{ConnectOptions, Connection};
// use std::str::FromStr;
pub async fn get_connection() -> Result<DatabaseConnection, DbErr> {
let config = config::get_config();
// Database::connect(config.primary_db.to_str().unwrap_or("sqlite::memory:")).await?;
// Connecting SQLite
let db_url = format!("{}{}", "sqlite://", config.primary_db.to_str().unwrap());
let db = Database::connect(&db_url).await?;
// Derive schema from Entity
let stmt = Schema::create_table_from_entity(file::Model);
// Execute create table statement
let result = db.execute(db.get_database_backend().build(&stmt)).await;
Ok(db)
}
pub async fn create_primary_db() -> Result<(), sqlx::Error> {
let config = config::get_config();
let db_url = config.primary_db.to_str().unwrap();
// establish connection, this is only used to create the db if missing
// replace in future
let mut connection = Connection::open(db_url).unwrap();
println!("Primary database initialized: {}", &db_url);
// migrate db
mod embedded_primary {
use refinery::embed_migrations;
embed_migrations!("src/db/migrations/primary");
}
embedded_primary::migrations::runner()
.run(&mut connection)
.unwrap();
// close and exit cause we don't need this connection anymore
connection.close().unwrap();
Ok(())
}

View file

@ -0,0 +1,19 @@
use crate::db::connection;
use rusqlite::Connection;
use std::io;
pub async fn migrate_primary() -> io::Result<()> {
let mut conn = Connection::open(connection::get_primary_db_url()).unwrap();
println!("Running migrations");
mod embedded_primary {
use refinery::embed_migrations;
embed_migrations!("src/db/migrations/primary");
}
embedded_primary::migrations::runner()
.run(&mut conn)
.unwrap();
Ok(())
}

View file

@ -0,0 +1,17 @@
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uri STRING NOT NULL,
meta_checksum STRING NOT NULL,
buffer_checksum STRING,
name STRING,
extension STRING,
size_in_bytes STRING NOT NULL,
encryption INTEGER DEFAULT 0,
ipfs_id STRING,
date_created TEXT NOT NULL,
date_modified TEXT NOT NULL,
date_indexed TEXT NOT NULL,
storage_device_id STRING,
capture_device_id STRING,
parent_file_id STRING
);

View file

@ -1 +1,2 @@
pub mod connection;
// pub mod migrate;

View file

@ -1,9 +1,11 @@
use crate::crypto;
use crate::db;
use crate::filesystem::checksum;
use crate::util::time;
use chrono::prelude::*;
use chrono::NaiveDateTime;
use chrono::{NaiveDateTime, Utc};
use sea_orm::entity::prelude::*;
use sea_orm::entity::*;
use sea_orm::InsertResult;
use serde::{Deserialize, Serialize};
use std::ffi::OsStr;
use std::fs;
@ -13,38 +15,37 @@ use std::path;
// -------------------------------------
// Entity: File
// Represents an item discovered on the filesystem
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "files")]
// -------------------------------------
pub struct Model {
// identity
#[sea_orm(primary_key)]
pub id: u64,
pub id: u32,
pub buffer_checksum: String,
pub meta_checksum: String,
pub uri: String,
// metadata
pub name: String,
pub extension: String,
pub size_in_bytes: u64,
pub size_in_bytes: String,
// pub encryption: crypto::Encryption,
#[sea_orm(nullable)]
pub ipfs_id: Option<String>,
// ownership
#[sea_orm(nullable)]
pub user_id: Option<u64>,
pub storage_device_id: Option<u32>,
#[sea_orm(nullable)]
pub storage_device_id: Option<u64>,
pub capture_device_id: Option<u32>,
#[sea_orm(nullable)]
pub capture_device_id: Option<u64>,
#[sea_orm(nullable)]
pub parent_file_id: Option<u64>,
pub parent_file_id: Option<u32>,
// date
pub date_created: NaiveDateTime,
pub date_modified: NaiveDateTime,
pub date_indexed: NaiveDateTime,
}
pub type File = Model;
pub type File = ActiveModel;
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
@ -53,39 +54,35 @@ impl ActiveModelBehavior for ActiveModel {}
// Read a file from path returning the File struct
// Generates meta checksum and extracts metadata
// pub async fn read_file(path: &str) -> io::Result<File> {
// let path_buff = path::PathBuf::from(path);
// let metadata = fs::metadata(&path)?;
pub async fn read_file(path: &str) -> io::Result<File> {
let db = db::connection::get_connection().await.unwrap();
// if metadata.is_dir() {
// // return Err();
// }
let path_buff = path::PathBuf::from(path);
let metadata = fs::metadata(&path)?;
// let size = metadata.len();
// let meta_checksum = checksum::create_meta_hash(path.to_owned(), size)?;
if metadata.is_dir() {
// return Err();
}
// // assemble File struct with initial values
// let file = File {
// name: extract_name(path_buff.file_name()),
// extension: extract_name(path_buff.extension()),
// uri: path.to_owned(),
// size_in_bytes: size,
// date_created: time::system_time_to_date_time(metadata.created()).unwrap_or(Utc::now()),
// date_modified: time::system_time_to_date_time(metadata.created()).unwrap_or(Utc::now()),
// date_indexed: Utc::now(),
// encryption: crypto::Encryption::NONE,
// // this will be populated later, either by the database or other functions
// id: None,
// meta_checksum,
// buffer_checksum: None,
// ipfs_id: None,
// user_id: None,
// storage_device_id: None,
// capture_device_id: None,
// parent_file_id: None,
// };
// Ok(file)
// }
let size = metadata.len();
let meta_checksum = checksum::create_meta_hash(path.to_owned(), size)?;
let file = File {
meta_checksum: Set(meta_checksum),
name: Set(extract_name(path_buff.file_name())),
extension: Set(extract_name(path_buff.extension())),
uri: Set(path.to_owned()),
size_in_bytes: Set(format!("{}", size)),
date_created: Set(time::system_time_to_date_time(metadata.created()).unwrap()),
date_modified: Set(time::system_time_to_date_time(metadata.modified()).unwrap()),
date_indexed: Set(time::system_time_to_date_time(metadata.modified()).unwrap()),
..Default::default()
};
let res = file.insert(&db).await.unwrap();
Ok(res)
}
// extract name from OsStr returned by PathBuff
fn extract_name(os_string: Option<&OsStr>) -> String {

View file

@ -4,7 +4,7 @@
)]
mod app;
// mod commands;
mod commands;
mod crypto;
mod db;
mod filesystem;
@ -13,15 +13,12 @@ use crate::app::menu;
use futures::executor::block_on;
fn main() {
let connection = db::connection::get_connection();
let connection = db::connection::create_primary_db();
let primary_db = block_on(connection).unwrap();
// db::migrate::run_migrations(connection);
println!("primary database connected {:?}", primary_db);
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
// commands::read_file_command,
commands::read_file_command,
// commands::generate_buffer_checksum
])
.menu(menu::get_menu())

View file

@ -1,16 +1,16 @@
use chrono::{offset::TimeZone, DateTime, NaiveDateTime, Utc};
use chrono::NaiveDateTime;
use std::io;
use std::time::{SystemTime, UNIX_EPOCH};
pub fn system_time_to_date_time(
system_time: io::Result<SystemTime>,
) -> Result<DateTime<Utc>, Box<dyn std::error::Error>> {
) -> Result<NaiveDateTime, Box<dyn std::error::Error>> {
// extract system time or resort to current time if failure
let system_time = system_time.unwrap_or(SystemTime::now());
let std_duration = system_time.duration_since(UNIX_EPOCH)?;
let chrono_duration = chrono::Duration::from_std(std_duration)?;
let unix = NaiveDateTime::from_timestamp(0, 0);
let naive = unix + chrono_duration;
let date_time: DateTime<Utc> = Utc.from_local_datetime(&naive).unwrap();
Ok(date_time)
// let date_time: DateTime<Utc> = Utc.from_local_datetime(&naive).unwrap();
Ok(naive)
}