Split out a support library
This commit is contained in:
parent
f3940111c4
commit
1b161435df
|
@ -6,6 +6,16 @@ edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
auth-cli = [ "clap" ]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "auth-cli"
|
||||||
|
path = "src/bin/cli.rs"
|
||||||
|
required-features = [ "auth-cli" ]
|
||||||
|
|
||||||
|
[target.auth-cli.dependencies]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
build_html = { version = "2" }
|
build_html = { version = "2" }
|
||||||
bytes = { version = "1" }
|
bytes = { version = "1" }
|
||||||
|
@ -28,6 +38,7 @@ tokio = { version = "1", features = [ "full" ] }
|
||||||
uuid = { version = "0.4", features = [ "serde", "v4" ] }
|
uuid = { version = "0.4", features = [ "serde", "v4" ] }
|
||||||
warp = { version = "0.3" }
|
warp = { version = "0.3" }
|
||||||
base64ct = { version = "1", features = [ "alloc" ] }
|
base64ct = { version = "1", features = [ "alloc" ] }
|
||||||
|
clap = { version = "4", features = [ "derive" ], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cool_asserts = { version = "2" }
|
cool_asserts = { version = "2" }
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use build_html::Html;
|
use build_html::Html;
|
||||||
use http::{Error, StatusCode};
|
use http::{Error, StatusCode};
|
||||||
use std::{collections::HashMap, future::Future};
|
use std::collections::HashMap;
|
||||||
use warp::http::Response;
|
use warp::http::Response;
|
||||||
|
|
||||||
use crate::{pages, App, AuthToken, FileHandle, FileId, FileInfo, ReadFileError, SessionToken};
|
use crate::{pages, App, AuthToken, FileId, FileInfo, ReadFileError, SessionToken};
|
||||||
|
|
||||||
pub async fn handle_index(
|
pub async fn handle_index(
|
||||||
app: App,
|
app: App,
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
mod store;
|
||||||
|
|
||||||
|
pub use store::{
|
||||||
|
AuthDB, AuthError, AuthToken, FileHandle, FileId, FileInfo, ReadFileError, SessionToken, Store,
|
||||||
|
Username, WriteFileError,
|
||||||
|
};
|
|
@ -8,25 +8,25 @@ use http::status::StatusCode;
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashSet,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
io::Read,
|
io::Read,
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{Arc, RwLock},
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use store::Username;
|
use tokio::sync::RwLock;
|
||||||
use warp::{filters::multipart::Part, Filter, Rejection};
|
use warp::{filters::multipart::Part, Filter, Rejection};
|
||||||
|
|
||||||
mod handlers;
|
mod handlers;
|
||||||
mod html;
|
mod html;
|
||||||
mod pages;
|
mod pages;
|
||||||
mod store;
|
|
||||||
|
|
||||||
pub use handlers::handle_index;
|
pub use file_service::{
|
||||||
pub use store::{
|
AuthDB, AuthError, AuthToken, FileHandle, FileId, FileInfo, ReadFileError, SessionToken, Store,
|
||||||
App, AuthDB, AuthToken, FileHandle, FileId, FileInfo, ReadFileError, SessionToken, Store,
|
Username, WriteFileError,
|
||||||
};
|
};
|
||||||
|
pub use handlers::handle_index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
async fn authenticate_user(app: App, auth_token: String) -> Result<Username, warp::Rejection> {
|
async fn authenticate_user(app: App, auth_token: String) -> Result<Username, warp::Rejection> {
|
||||||
|
@ -112,6 +112,45 @@ async fn handle_upload(
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct App {
|
||||||
|
authdb: Arc<RwLock<AuthDB>>,
|
||||||
|
store: Arc<RwLock<Store>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
pub fn new(authdb: AuthDB, store: Store) -> Self {
|
||||||
|
Self {
|
||||||
|
authdb: Arc::new(RwLock::new(authdb)),
|
||||||
|
store: Arc::new(RwLock::new(store)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn auth_token(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
||||||
|
self.authdb.read().await.auth_token(token).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn auth_session(&self, token: SessionToken) -> Result<Option<Username>, AuthError> {
|
||||||
|
self.authdb.read().await.auth_session(token).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_files(&self) -> Result<HashSet<FileId>, ReadFileError> {
|
||||||
|
self.store.read().await.list_files()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_file(&self, id: &FileId) -> Result<FileHandle, ReadFileError> {
|
||||||
|
self.store.read().await.get_file(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_file(
|
||||||
|
&self,
|
||||||
|
filename: String,
|
||||||
|
content: Vec<u8>,
|
||||||
|
) -> Result<FileHandle, WriteFileError> {
|
||||||
|
self.store.write().await.add_file(filename, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn with_app(app: App) -> impl Filter<Extract = (App,), Error = Infallible> + Clone {
|
fn with_app(app: App) -> impl Filter<Extract = (App,), Error = Infallible> + Clone {
|
||||||
warp::any().map(move || app.clone())
|
warp::any().map(move || app.clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use crate::{
|
use crate::html::*;
|
||||||
html::*,
|
|
||||||
store::{FileHandle, FileId, ReadFileError},
|
|
||||||
};
|
|
||||||
use build_html::{self, Container, ContainerType, Html, HtmlContainer};
|
use build_html::{self, Container, ContainerType, Html, HtmlContainer};
|
||||||
|
use file_service::{FileHandle, FileId, ReadFileError};
|
||||||
|
|
||||||
pub fn auth(_message: Option<String>) -> build_html::HtmlPage {
|
pub fn auth(_message: Option<String>) -> build_html::HtmlPage {
|
||||||
build_html::HtmlPage::new()
|
build_html::HtmlPage::new()
|
||||||
|
|
|
@ -242,45 +242,6 @@ impl FileRoot for Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct App {
|
|
||||||
authdb: Arc<RwLock<AuthDB>>,
|
|
||||||
store: Arc<RwLock<Store>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl App {
|
|
||||||
pub fn new(authdb: AuthDB, store: Store) -> Self {
|
|
||||||
Self {
|
|
||||||
authdb: Arc::new(RwLock::new(authdb)),
|
|
||||||
store: Arc::new(RwLock::new(store)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn auth_token(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
|
||||||
self.authdb.read().await.auth_token(token).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn auth_session(&self, token: SessionToken) -> Result<Option<Username>, AuthError> {
|
|
||||||
self.authdb.read().await.auth_session(token).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list_files(&self) -> Result<HashSet<FileId>, ReadFileError> {
|
|
||||||
self.store.read().await.list_files()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_file(&self, id: &FileId) -> Result<FileHandle, ReadFileError> {
|
|
||||||
self.store.read().await.get_file(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn add_file(
|
|
||||||
&self,
|
|
||||||
filename: String,
|
|
||||||
content: Vec<u8>,
|
|
||||||
) -> Result<FileHandle, WriteFileError> {
|
|
||||||
self.store.write().await.add_file(filename, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AuthDB {
|
pub struct AuthDB {
|
||||||
pool: SqlitePool,
|
pool: SqlitePool,
|
||||||
|
@ -294,7 +255,7 @@ impl AuthDB {
|
||||||
Ok(Self { pool })
|
Ok(Self { pool })
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_user(&self, username: Username) -> Result<AuthToken, AuthError> {
|
pub async fn add_user(&self, username: Username) -> Result<AuthToken, AuthError> {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(Uuid::new_v4().hyphenated().to_string());
|
hasher.update(Uuid::new_v4().hyphenated().to_string());
|
||||||
hasher.update(username.to_string());
|
hasher.update(username.to_string());
|
||||||
|
@ -309,7 +270,7 @@ impl AuthDB {
|
||||||
Ok(AuthToken::from(auth_token))
|
Ok(AuthToken::from(auth_token))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_users(&self) -> Result<Vec<Username>, AuthError> {
|
pub async fn list_users(&self) -> Result<Vec<Username>, AuthError> {
|
||||||
let usernames = sqlx::query_as::<_, Username>("SELECT (username) FROM users")
|
let usernames = sqlx::query_as::<_, Username>("SELECT (username) FROM users")
|
||||||
.fetch_all(&self.pool)
|
.fetch_all(&self.pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -317,7 +278,7 @@ impl AuthDB {
|
||||||
Ok(usernames)
|
Ok(usernames)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn auth_token(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
pub async fn auth_token(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
||||||
let results = sqlx::query("SELECT * FROM users WHERE token = $1")
|
let results = sqlx::query("SELECT * FROM users WHERE token = $1")
|
||||||
.bind(token.to_string())
|
.bind(token.to_string())
|
||||||
.fetch_all(&self.pool)
|
.fetch_all(&self.pool)
|
||||||
|
@ -347,7 +308,7 @@ impl AuthDB {
|
||||||
Ok(Some(SessionToken::from(session_token)))
|
Ok(Some(SessionToken::from(session_token)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn auth_session(&self, token: SessionToken) -> Result<Option<Username>, AuthError> {
|
pub async fn auth_session(&self, token: SessionToken) -> Result<Option<Username>, AuthError> {
|
||||||
let rows = sqlx::query(
|
let rows = sqlx::query(
|
||||||
"SELECT users.username FROM sessions INNER JOIN users ON sessions.user_id = users.id WHERE sessions.token = $1",
|
"SELECT users.username FROM sessions INNER JOIN users ON sessions.user_id = users.id WHERE sessions.token = $1",
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue