mirror of https://github.com/raftario/filite.git
Some queries and models
This commit is contained in:
parent
10d063c0da
commit
013c3f5ca8
|
@ -285,6 +285,8 @@ dependencies = [
|
|||
"anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-argon2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -376,6 +378,17 @@ name = "futures-io"
|
|||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.5"
|
||||
|
@ -397,11 +410,14 @@ dependencies = [
|
|||
"futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pin-project 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -959,6 +975,16 @@ dependencies = [
|
|||
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.18"
|
||||
|
@ -1860,6 +1886,7 @@ dependencies = [
|
|||
"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
|
||||
"checksum futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
|
||||
"checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
|
||||
"checksum futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
|
||||
"checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
|
||||
"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
|
||||
"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
|
||||
|
@ -1925,6 +1952,8 @@ dependencies = [
|
|||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
"checksum proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
|
||||
"checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
|
||||
"checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
|
||||
"checksum proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
|
||||
"checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
|
|
|
@ -18,16 +18,19 @@ license = "MIT"
|
|||
anyhow = "1.0.31"
|
||||
cfg-if = "0.1.10"
|
||||
chrono = "0.4.11"
|
||||
futures-core = "0.3.5"
|
||||
futures-util = "0.3.5"
|
||||
log = { version = "0.4.8", features = ["serde"] }
|
||||
rust-argon2 = "0.8.2"
|
||||
serde = { version = "1.0.114", features = ["derive"] }
|
||||
serde_json = "1.0.55"
|
||||
sqlx = { version = "0.3.5", features = ["chrono", "runtime-tokio"], default-features = false }
|
||||
sqlx = { version = "0.3.5", features = ["chrono", "macros", "runtime-tokio"], default-features = false }
|
||||
structopt = "0.3.15"
|
||||
tokio = { version = "0.2.21", features = ["blocking", "fs", "rt-core"] }
|
||||
warp = { version = "0.2.3", features = ["multipart"], default-features = false }
|
||||
|
||||
# Makes cross-compiliing easier by statically linking to OpenSSL
|
||||
[target.'cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))'.dependencies]
|
||||
openssl-sys = { version = "0.9", features = ["vendored"] }
|
||||
|
||||
[features]
|
||||
|
|
110
src/db/mod.rs
110
src/db/mod.rs
|
@ -1 +1,111 @@
|
|||
pub mod models;
|
||||
pub mod pool;
|
||||
|
||||
use anyhow::Error;
|
||||
use futures_core::Stream;
|
||||
use futures_util::StreamExt;
|
||||
use models::{Filite, FiliteRow, User, UserRow};
|
||||
use pool::Pool;
|
||||
use std::{convert::TryInto, pin::Pin};
|
||||
|
||||
pub async fn fetch(id: &str, pool: &Pool) -> Result<Option<Filite>, Error> {
|
||||
let sql = "SELECT * FROM data WHERE id = ?";
|
||||
let row: Option<FiliteRow> = match pool {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Pool::Sqlite(p) => {
|
||||
use sqlx::sqlite::SqliteQueryAs;
|
||||
sqlx::query_as(sql).bind(id).fetch_optional(p).await?
|
||||
}
|
||||
#[cfg(feature = "postgres")]
|
||||
Pool::Postgres(p) => {
|
||||
use sqlx::postgres::PgQueryAs;
|
||||
sqlx::query_as(sql).bind(id).fetch_optional(p).await?
|
||||
}
|
||||
#[cfg(feature = "mysql")]
|
||||
Pool::MySql(p) => {
|
||||
use sqlx::mysql::MySqlQueryAs;
|
||||
sqlx::query_as(sql).bind(id).fetch_optional(p).await?
|
||||
}
|
||||
};
|
||||
let filite: Option<Filite> = match row {
|
||||
Some(row) => Some(row.try_into()?),
|
||||
None => None,
|
||||
};
|
||||
Ok(filite)
|
||||
}
|
||||
|
||||
pub fn fetch_all<'a>(pool: &'a Pool) -> impl Stream<Item = Result<Filite, Error>> + 'a {
|
||||
let sql = "SELECT * FROM data";
|
||||
let rows: Pin<Box<dyn Stream<Item = Result<FiliteRow, sqlx::Error>>>> = match pool {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Pool::Sqlite(p) => {
|
||||
use sqlx::sqlite::SqliteQueryAs;
|
||||
sqlx::query_as(sql).fetch(p)
|
||||
}
|
||||
#[cfg(feature = "postgres")]
|
||||
Pool::Postgres(p) => {
|
||||
use sqlx::postgres::PgQueryAs;
|
||||
sqlx::query_as(sql).fetch(p)
|
||||
}
|
||||
#[cfg(feature = "mysql")]
|
||||
Pool::MySql(p) => {
|
||||
use sqlx::mysql::MySqlQueryAs;
|
||||
sqlx::query_as(sql).fetch(p)
|
||||
}
|
||||
};
|
||||
rows.map(|r| match r {
|
||||
Ok(r) => r.try_into(),
|
||||
Err(e) => Err(e.into()),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn fetch_user(username: &str, pool: &Pool) -> Result<Option<User>, Error> {
|
||||
let sql = "SELECT * FROM users WHERE username = ?";
|
||||
let row: Option<UserRow> = match pool {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Pool::Sqlite(p) => {
|
||||
use sqlx::sqlite::SqliteQueryAs;
|
||||
sqlx::query_as(sql).bind(username).fetch_optional(p).await?
|
||||
}
|
||||
#[cfg(feature = "postgres")]
|
||||
Pool::Postgres(p) => {
|
||||
use sqlx::postgres::PgQueryAs;
|
||||
sqlx::query_as(sql).bind(username).fetch_optional(p).await?
|
||||
}
|
||||
#[cfg(feature = "mysql")]
|
||||
Pool::MySql(p) => {
|
||||
use sqlx::mysql::MySqlQueryAs;
|
||||
sqlx::query_as(sql).bind(username).fetch_optional(p).await?
|
||||
}
|
||||
};
|
||||
let user: Option<User> = match row {
|
||||
Some(row) => Some(row.try_into()?),
|
||||
None => None,
|
||||
};
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
pub fn fetch_all_users<'a>(pool: &'a Pool) -> impl Stream<Item = Result<User, Error>> + 'a {
|
||||
let sql = "SELECT * FROM users";
|
||||
let rows: Pin<Box<dyn Stream<Item = Result<UserRow, sqlx::Error>>>> = match pool {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Pool::Sqlite(p) => {
|
||||
use sqlx::sqlite::SqliteQueryAs;
|
||||
sqlx::query_as(sql).fetch(p)
|
||||
}
|
||||
#[cfg(feature = "postgres")]
|
||||
Pool::Postgres(p) => {
|
||||
use sqlx::postgres::PgQueryAs;
|
||||
sqlx::query_as(sql).fetch(p)
|
||||
}
|
||||
#[cfg(feature = "mysql")]
|
||||
Pool::MySql(p) => {
|
||||
use sqlx::mysql::MySqlQueryAs;
|
||||
sqlx::query_as(sql).fetch(p)
|
||||
}
|
||||
};
|
||||
rows.map(|r| match r {
|
||||
Ok(r) => r.try_into(),
|
||||
Err(e) => Err(e.into()),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
use anyhow::{anyhow, Error};
|
||||
// use chrono::{DateTime, Utc};
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
path::PathBuf,
|
||||
};
|
||||
use tokio::task;
|
||||
|
||||
#[derive(sqlx::FromRow)]
|
||||
pub struct FiliteRow {
|
||||
id: String,
|
||||
ty: i32,
|
||||
val: String,
|
||||
creator: String,
|
||||
// created: DateTime<Utc>,
|
||||
visibility: i32,
|
||||
views: i32,
|
||||
}
|
||||
|
||||
pub enum Filite {
|
||||
File {
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
creator: String,
|
||||
// created: DateTime<Utc>,
|
||||
visibility: Visibility,
|
||||
#[cfg(feature = "analytics")]
|
||||
views: i32,
|
||||
},
|
||||
Link {
|
||||
id: String,
|
||||
url: String,
|
||||
creator: String,
|
||||
// created: DateTime<Utc>,
|
||||
visibility: Visibility,
|
||||
#[cfg(feature = "analytics")]
|
||||
views: i32,
|
||||
},
|
||||
Text {
|
||||
id: String,
|
||||
contents: String,
|
||||
creator: String,
|
||||
// created: DateTime<Utc>,
|
||||
visibility: Visibility,
|
||||
#[cfg(feature = "analytics")]
|
||||
views: i32,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum Visibility {
|
||||
Public,
|
||||
Internal,
|
||||
Private,
|
||||
}
|
||||
|
||||
impl TryFrom<FiliteRow> for Filite {
|
||||
type Error = Error;
|
||||
fn try_from(row: FiliteRow) -> Result<Self, Self::Error> {
|
||||
match row.ty {
|
||||
0 => Ok(Filite::File {
|
||||
id: row.id,
|
||||
path: PathBuf::from(row.val),
|
||||
creator: row.creator,
|
||||
// created: row.created,
|
||||
visibility: row.visibility.try_into()?,
|
||||
#[cfg(feature = "analytics")]
|
||||
views: row.views,
|
||||
}),
|
||||
1 => Ok(Filite::Link {
|
||||
id: row.id,
|
||||
url: row.val,
|
||||
creator: row.creator,
|
||||
// created: row.created,
|
||||
visibility: row.visibility.try_into()?,
|
||||
#[cfg(feature = "analytics")]
|
||||
views: row.views,
|
||||
}),
|
||||
2 => Ok(Filite::Text {
|
||||
id: row.id,
|
||||
contents: row.val,
|
||||
creator: row.creator,
|
||||
// created: row.created,
|
||||
visibility: row.visibility.try_into()?,
|
||||
#[cfg(feature = "analytics")]
|
||||
views: row.views,
|
||||
}),
|
||||
ty => Err(anyhow!("unknown type {}", ty)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<i32> for Visibility {
|
||||
type Error = Error;
|
||||
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
0 => Ok(Visibility::Public),
|
||||
1 => Ok(Visibility::Internal),
|
||||
2 => Ok(Visibility::Private),
|
||||
_ => Err(anyhow!("unknown visibility {}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow)]
|
||||
pub struct UserRow {
|
||||
username: String,
|
||||
password: String,
|
||||
role: i32,
|
||||
// registered: DateTime<Utc>,
|
||||
}
|
||||
|
||||
pub struct User {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
pub role: Role,
|
||||
// pub registered: DateTime<Utc>,
|
||||
}
|
||||
|
||||
pub enum Role {
|
||||
User,
|
||||
Admin,
|
||||
}
|
||||
|
||||
impl TryFrom<UserRow> for User {
|
||||
type Error = Error;
|
||||
fn try_from(value: UserRow) -> Result<Self, Self::Error> {
|
||||
Ok(User {
|
||||
username: value.username,
|
||||
password: value.password,
|
||||
role: value.role.try_into()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<i32> for Role {
|
||||
type Error = Error;
|
||||
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
0 => Ok(Role::User),
|
||||
1 => Ok(Role::Admin),
|
||||
_ => Err(anyhow!("unknown role {}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub async fn verify_password(&self, password: &str) -> Result<bool, Error> {
|
||||
let encoded = self.password.clone();
|
||||
let pwd = password.as_bytes().to_vec();
|
||||
Ok(task::spawn_blocking(move || argon2::verify_encoded(&encoded, &pwd)).await??)
|
||||
}
|
||||
}
|
|
@ -63,17 +63,3 @@ impl Pool {
|
|||
builder
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pool {
|
||||
($pool:expr) => {{
|
||||
match $pool {
|
||||
#[cfg(feature = "sqlite")]
|
||||
$crate::db::Pool::Sqlite(p) => p,
|
||||
#[cfg(feature = "postgres")]
|
||||
$crate::db::Pool::Postgres(p) => p,
|
||||
#[cfg(feature = "mysql")]
|
||||
$crate::db::Pool::Mysql(p) => p,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue