From 338b1eb0d3991ddd51188ca1364a8f43606285ee Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 1 Oct 2021 10:23:50 -0700 Subject: [PATCH] checkpoint before potentially removing seaorm --- package.json | 2 +- src-tauri/Cargo.lock | 74 +++++++++++++++++ src-tauri/Cargo.toml | 3 + src-tauri/src/commands.rs | 22 +++--- src-tauri/src/db/connection.rs | 40 +++++++--- src-tauri/src/db/migrate.rs | 19 +++++ .../src/db/migrations/primary/V1__initial.sql | 17 ++++ src-tauri/src/db/mod.rs | 1 + src-tauri/src/filesystem/file.rs | 79 +++++++++---------- src-tauri/src/main.rs | 9 +-- src-tauri/src/util/time.rs | 8 +- 11 files changed, 201 insertions(+), 73 deletions(-) create mode 100644 src-tauri/src/db/migrate.rs create mode 100644 src-tauri/src/db/migrations/primary/V1__initial.sql diff --git a/package.json b/package.json index 6960bfa7b..ca850e4f2 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "sd-client", + "name": "drive", "version": "1.0.0", "main": "index.js", "license": "MIT", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 742b0a57a..92935cec7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -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", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 62c65a572..4298c1247 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -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] diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 2359e7a49..da3f05391 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -5,21 +5,21 @@ use crate::filesystem::file::File; use tauri::InvokeError; #[tauri::command(async)] -pub async fn read_file_command(path: &str) -> Result { +pub async fn read_file_command(path: &str) -> Result { 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 { - 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 { +// 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) +// } diff --git a/src-tauri/src/db/connection.rs b/src-tauri/src/db/connection.rs index c3023d6db..c2c41649c 100644 --- a/src-tauri/src/db/connection.rs +++ b/src-tauri/src/db/connection.rs @@ -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 { 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(()) +} diff --git a/src-tauri/src/db/migrate.rs b/src-tauri/src/db/migrate.rs new file mode 100644 index 000000000..c38db3b30 --- /dev/null +++ b/src-tauri/src/db/migrate.rs @@ -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(()) +} diff --git a/src-tauri/src/db/migrations/primary/V1__initial.sql b/src-tauri/src/db/migrations/primary/V1__initial.sql new file mode 100644 index 000000000..30684350e --- /dev/null +++ b/src-tauri/src/db/migrations/primary/V1__initial.sql @@ -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 +); \ No newline at end of file diff --git a/src-tauri/src/db/mod.rs b/src-tauri/src/db/mod.rs index b3b606b40..96e5461de 100644 --- a/src-tauri/src/db/mod.rs +++ b/src-tauri/src/db/mod.rs @@ -1 +1,2 @@ pub mod connection; +// pub mod migrate; diff --git a/src-tauri/src/filesystem/file.rs b/src-tauri/src/filesystem/file.rs index 3de93fc78..afd792028 100644 --- a/src-tauri/src/filesystem/file.rs +++ b/src-tauri/src/filesystem/file.rs @@ -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, // ownership #[sea_orm(nullable)] - pub user_id: Option, + pub storage_device_id: Option, #[sea_orm(nullable)] - pub storage_device_id: Option, + pub capture_device_id: Option, #[sea_orm(nullable)] - pub capture_device_id: Option, - #[sea_orm(nullable)] - pub parent_file_id: Option, + pub parent_file_id: Option, // 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 { -// let path_buff = path::PathBuf::from(path); -// let metadata = fs::metadata(&path)?; +pub async fn read_file(path: &str) -> io::Result { + 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 { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d1c4523d1..9338145d4 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -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()) diff --git a/src-tauri/src/util/time.rs b/src-tauri/src/util/time.rs index 8cd65fda4..cd9395651 100644 --- a/src-tauri/src/util/time.rs +++ b/src-tauri/src/util/time.rs @@ -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, -) -> Result, Box> { +) -> Result> { // 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.from_local_datetime(&naive).unwrap(); - Ok(date_time) + // let date_time: DateTime = Utc.from_local_datetime(&naive).unwrap(); + Ok(naive) }