Import and update the file service application and orizentic #72
|
@ -4,4 +4,6 @@ node_modules
|
||||||
dist
|
dist
|
||||||
result
|
result
|
||||||
*.tgz
|
*.tgz
|
||||||
file-service/auth.sqlite
|
file-service/*.sqlite
|
||||||
|
file-service/*.sqlite-shm
|
||||||
|
file-service/*.sqlite-wal
|
||||||
|
|
|
@ -416,7 +416,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.29",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -471,6 +471,16 @@ version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cookie"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24"
|
||||||
|
dependencies = [
|
||||||
|
"time 0.3.29",
|
||||||
|
"version_check 0.9.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cool_asserts"
|
name = "cool_asserts"
|
||||||
version = "2.0.3"
|
version = "2.0.3"
|
||||||
|
@ -661,6 +671,12 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
|
@ -842,6 +858,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap 4.4.6",
|
"clap 4.4.6",
|
||||||
|
"cookie",
|
||||||
"cool_asserts",
|
"cool_asserts",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex-string",
|
"hex-string",
|
||||||
|
@ -1744,7 +1761,7 @@ dependencies = [
|
||||||
"log 0.3.9",
|
"log 0.3.9",
|
||||||
"mime 0.2.6",
|
"mime 0.2.6",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"time",
|
"time 0.1.45",
|
||||||
"traitobject",
|
"traitobject",
|
||||||
"typeable",
|
"typeable",
|
||||||
"unicase 1.4.2",
|
"unicase 1.4.2",
|
||||||
|
@ -2178,7 +2195,7 @@ checksum = "6c9172cb4c2f6c52117e25570983edcbb322f130b1031ae5d5d6b1abe7eeb493"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iron",
|
"iron",
|
||||||
"log 0.3.9",
|
"log 0.3.9",
|
||||||
"time",
|
"time 0.1.45",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3942,6 +3959,34 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"itoa",
|
||||||
|
"serde 1.0.188",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
||||||
|
dependencies = [
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
|
|
|
@ -25,9 +25,12 @@ required-features = [ "auth-cli" ]
|
||||||
[target.auth-cli.dependencies]
|
[target.auth-cli.dependencies]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
base64ct = { version = "1", features = [ "alloc" ] }
|
||||||
build_html = { version = "2" }
|
build_html = { version = "2" }
|
||||||
bytes = { version = "1" }
|
bytes = { version = "1" }
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
clap = { version = "4", features = [ "derive" ], optional = true }
|
||||||
|
cookie = { version = "0.17" }
|
||||||
futures-util = { version = "0.3" }
|
futures-util = { version = "0.3" }
|
||||||
hex-string = "0.1.0"
|
hex-string = "0.1.0"
|
||||||
http = { version = "0.2" }
|
http = { version = "0.2" }
|
||||||
|
@ -45,8 +48,6 @@ thiserror = "1.0.20"
|
||||||
tokio = { version = "1", features = [ "full" ] }
|
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" ] }
|
|
||||||
clap = { version = "4", features = [ "derive" ], optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cool_asserts = { version = "2" }
|
cool_asserts = { version = "2" }
|
||||||
|
|
|
@ -10,9 +10,9 @@ pub async fn handle_index(
|
||||||
token: Option<SessionToken>,
|
token: Option<SessionToken>,
|
||||||
) -> Result<Response<String>, Error> {
|
) -> Result<Response<String>, Error> {
|
||||||
match token {
|
match token {
|
||||||
Some(token) => match app.auth_session(token).await {
|
Some(token) => match app.validate_session(token).await {
|
||||||
Ok(_) => render_gallery_page(app).await,
|
Ok(_) => render_gallery_page(app).await,
|
||||||
Err(err) => render_auth_page(Some(format!("authentication refused: {:?}", err))),
|
Err(err) => render_auth_page(Some(format!("session expired: {:?}", err))),
|
||||||
},
|
},
|
||||||
None => render_auth_page(None),
|
None => render_auth_page(None),
|
||||||
}
|
}
|
||||||
|
@ -76,10 +76,21 @@ pub async fn handle_auth(
|
||||||
) -> Result<http::Response<String>, Error> {
|
) -> Result<http::Response<String>, Error> {
|
||||||
match form.get("token") {
|
match form.get("token") {
|
||||||
Some(token) => match app
|
Some(token) => match app
|
||||||
.auth_token(AuthToken::from(AuthToken::from(token.clone())))
|
.authenticate(AuthToken::from(AuthToken::from(token.clone())))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_session_token) => render_gallery_page(app).await,
|
Ok(Some(session_token)) => Response::builder()
|
||||||
|
.header("location", "/")
|
||||||
|
.header(
|
||||||
|
"set-cookie",
|
||||||
|
format!(
|
||||||
|
"session={}; Secure; HttpOnly; SameSite=Strict",
|
||||||
|
session_token.to_string()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.status(StatusCode::SEE_OTHER)
|
||||||
|
.body("".to_owned()),
|
||||||
|
Ok(None) => render_auth_page(Some(format!("no user found"))),
|
||||||
Err(_) => render_auth_page(Some(format!("invalid auth token"))),
|
Err(_) => render_auth_page(Some(format!("invalid auth token"))),
|
||||||
},
|
},
|
||||||
None => render_auth_page(Some(format!("no token available"))),
|
None => render_auth_page(Some(format!("no token available"))),
|
||||||
|
|
|
@ -6,9 +6,10 @@ use http::status::StatusCode;
|
||||||
// use mustache::{compile_path, Template};
|
// use mustache::{compile_path, Template};
|
||||||
// use orizentic::{Permissions, ResourceName, Secret};
|
// use orizentic::{Permissions, ResourceName, Secret};
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
|
use cookie::Cookie;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::{HashMap, HashSet},
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
io::Read,
|
io::Read,
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
|
@ -126,12 +127,15 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn auth_token(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
pub async fn authenticate(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
||||||
self.authdb.read().await.auth_token(token).await
|
self.authdb.read().await.authenticate(token).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn auth_session(&self, token: SessionToken) -> Result<Option<Username>, AuthError> {
|
pub async fn validate_session(
|
||||||
self.authdb.read().await.auth_session(token).await
|
&self,
|
||||||
|
token: SessionToken,
|
||||||
|
) -> Result<Option<Username>, AuthError> {
|
||||||
|
self.authdb.read().await.validate_session(token).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_files(&self) -> Result<HashSet<FileId>, ReadFileError> {
|
pub async fn list_files(&self) -> Result<HashSet<FileId>, ReadFileError> {
|
||||||
|
@ -159,9 +163,23 @@ fn maybe_with_session() -> impl Filter<Extract = (Option<SessionToken>,), Error
|
||||||
{
|
{
|
||||||
warp::any()
|
warp::any()
|
||||||
.and(warp::header::optional::<String>("cookie"))
|
.and(warp::header::optional::<String>("cookie"))
|
||||||
.map(|cookies| {
|
.map(|cookies| match cookies {
|
||||||
println!("cookies retrieved: {:?}", cookies);
|
Some(cookies) => {
|
||||||
|
let c = Cookie::split_parse(cookies)
|
||||||
|
.collect::<Result<Vec<Cookie>, cookie::ParseError>>();
|
||||||
|
match c {
|
||||||
|
Ok(cookies) => {
|
||||||
|
for c in cookies {
|
||||||
|
if c.name() == "session" {
|
||||||
|
return Some(SessionToken::from(c.value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
None
|
None
|
||||||
|
}
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -278,7 +278,7 @@ impl AuthDB {
|
||||||
Ok(usernames)
|
Ok(usernames)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn auth_token(&self, token: AuthToken) -> Result<Option<SessionToken>, AuthError> {
|
pub async fn authenticate(&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)
|
||||||
|
@ -308,7 +308,10 @@ impl AuthDB {
|
||||||
Ok(Some(SessionToken::from(session_token)))
|
Ok(Some(SessionToken::from(session_token)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn auth_session(&self, token: SessionToken) -> Result<Option<Username>, AuthError> {
|
pub async fn validate_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",
|
||||||
)
|
)
|
||||||
|
@ -498,7 +501,7 @@ mod authdb_test {
|
||||||
|
|
||||||
let token = AuthToken::from("0000000000");
|
let token = AuthToken::from("0000000000");
|
||||||
|
|
||||||
assert_matches!(db.auth_token(token).await, Ok(None));
|
assert_matches!(db.authenticate(token).await, Ok(None));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -511,7 +514,7 @@ mod authdb_test {
|
||||||
.await
|
.await
|
||||||
.expect("user to be created");
|
.expect("user to be created");
|
||||||
|
|
||||||
assert_matches!(db.auth_token(token).await, Ok(_));
|
assert_matches!(db.authenticate(token).await, Ok(_));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -524,13 +527,13 @@ mod authdb_test {
|
||||||
.await
|
.await
|
||||||
.expect("user to be created");
|
.expect("user to be created");
|
||||||
let session = db
|
let session = db
|
||||||
.auth_token(token)
|
.authenticate(token)
|
||||||
.await
|
.await
|
||||||
.expect("token authentication should succeed")
|
.expect("token authentication should succeed")
|
||||||
.expect("session token should be found");
|
.expect("session token should be found");
|
||||||
|
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.auth_session(session).await,
|
db.validate_session(session).await,
|
||||||
Ok(Some(username)) => {
|
Ok(Some(username)) => {
|
||||||
assert_eq!(username, Username::from("savanni"));
|
assert_eq!(username, Username::from("savanni"));
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue