aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock45
-rw-r--r--Cargo.toml8
-rw-r--r--src/args.rs18
-rw-r--r--src/auth.rs64
-rw-r--r--src/errors.rs13
-rw-r--r--src/main.rs31
-rw-r--r--tests/cli.rs4
7 files changed, 67 insertions, 116 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f719dbf..b060073 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -565,9 +565,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "3.0.0-beta.4"
+version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcd70aa5597dbc42f7217a543f9ef2768b2ef823ba29036072d30e1d88e98406"
+checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
dependencies = [
"atty",
"bitflags",
@@ -579,14 +579,14 @@ dependencies = [
"termcolor",
"terminal_size",
"textwrap 0.14.2",
- "vec_map",
+ "unicase",
]
[[package]]
name = "clap_derive"
-version = "3.0.0-beta.4"
+version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac"
+checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
dependencies = [
"heck",
"proc-macro-error",
@@ -597,11 +597,11 @@ dependencies = [
[[package]]
name = "clap_generate"
-version = "3.0.0-beta.4"
+version = "3.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d9b1abef93569f290952eff3c4a0a92d6767bb5158db095b4dc9a512b1c3643"
+checksum = "097ab5db1c3417442270cd57c8dd39f6c3114d3ce09d595f9efddbb1fcfaa799"
dependencies = [
- "clap 3.0.0-beta.4",
+ "clap 3.0.0-beta.5",
]
[[package]]
@@ -1407,7 +1407,7 @@ dependencies = [
"bytesize",
"chrono",
"chrono-humanize",
- "clap 3.0.0-beta.4",
+ "clap 3.0.0-beta.5",
"clap_generate",
"futures",
"get_if_addrs",
@@ -1571,9 +1571,12 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "os_str_bytes"
-version = "3.1.0"
+version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6acbef58a60fe69ab50510a55bc8cdd4d6cf2283d27ad338f54cb52747a9cf2d"
+checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
+dependencies = [
+ "memchr",
+]
[[package]]
name = "output_vt100"
@@ -2004,9 +2007,9 @@ dependencies = [
[[package]]
name = "reqwest"
-version = "0.11.5"
+version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51c732d463dd300362ffb44b7b125f299c23d2990411a4253824630ebc7467fb"
+checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280"
dependencies = [
"base64",
"bytes",
@@ -2420,15 +2423,15 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
-version = "0.21.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
+checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e"
[[package]]
name = "strum_macros"
-version = "0.21.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
+checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb"
dependencies = [
"heck",
"proc-macro2",
@@ -2523,18 +2526,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.29"
+version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.29"
+version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index ab3a6a8..c81fdbe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,8 +30,8 @@ port_check = "0.1"
bytesize = "1"
nanoid = "0.4"
alphanumeric-sort = "1"
-clap = { version = "3.0.0-beta.4", features = ["wrap_help"] }
-clap_generate = "3.0.0-beta.4"
+clap = { version = "3.0.0-beta.5", features = ["wrap_help"] }
+clap_generate = "3.0.0-beta.5"
chrono = "0.4"
chrono-humanize = "0.2"
serde = { version = "1", features = ["derive"] }
@@ -41,8 +41,8 @@ libflate = "1"
thiserror = "1"
anyhow = "1"
log = "0.4"
-strum = "0.21"
-strum_macros = "0.21"
+strum = "0.22"
+strum_macros = "0.22"
sha2 = "0.9"
hex = "0.4"
zip = "0.5.11"
diff --git a/src/args.rs b/src/args.rs
index 5595bea..40d34e9 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -1,4 +1,4 @@
-use clap::{Clap, ValueHint};
+use clap::{Parser, ValueHint};
use clap_generate::Shell;
use http::header::{HeaderMap, HeaderName, HeaderValue};
use std::net::IpAddr;
@@ -8,14 +8,8 @@ use crate::auth;
use crate::errors::ContextualError;
use crate::renderer;
-#[derive(Clap)]
-#[clap(
- name = "miniserve",
- author,
- about,
- version,
- setting = clap::AppSettings::ColoredHelp,
-)]
+#[derive(Parser)]
+#[clap(name = "miniserve", author, about, version)]
pub struct CliArgs {
/// Be verbose, includes emitting access logs
#[clap(short = 'v', long = "verbose")]
@@ -83,7 +77,7 @@ pub struct CliArgs {
short = 'c',
long = "color-scheme",
default_value = "squirrel",
- possible_values = &renderer::THEME_SLUGS,
+ possible_values = &*renderer::THEME_SLUGS,
case_insensitive = true,
)]
pub color_scheme: String,
@@ -93,7 +87,7 @@ pub struct CliArgs {
short = 'd',
long = "color-scheme-dark",
default_value = "archlinux",
- possible_values = &renderer::THEME_SLUGS,
+ possible_values = &*renderer::THEME_SLUGS,
case_insensitive = true,
)]
pub color_scheme_dark: String,
@@ -155,7 +149,7 @@ pub struct CliArgs {
pub show_wget_footer: bool,
/// Generate completion file for a shell
- #[clap(long = "print-completions", value_name = "shell", possible_values = &Shell::variants())]
+ #[clap(long = "print-completions", value_name = "shell", arg_enum)]
pub print_completions: Option<Shell>,
/// TLS certificate to use
diff --git a/src/auth.rs b/src/auth.rs
index 82b407c..b4717d1 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -1,8 +1,7 @@
-use actix_web::dev::{Service, ServiceRequest, ServiceResponse};
-use actix_web::{HttpRequest, ResponseError};
-use futures::future::Either;
+use actix_web::dev::ServiceRequest;
+use actix_web::HttpMessage;
+use actix_web_httpauth::extractors::basic::BasicAuth;
use sha2::{Digest, Sha256, Sha512};
-use std::future::{ready, Future};
use crate::errors::ContextualError;
@@ -13,16 +12,12 @@ pub struct BasicAuthParams {
pub password: String,
}
-impl BasicAuthParams {
- fn try_from_request(req: &HttpRequest) -> actix_web::Result<Self> {
- use actix_web::http::header::Header;
- use actix_web_httpauth::headers::authorization::{Authorization, Basic};
-
- let auth = Authorization::<Basic>::parse(req)?.into_scheme();
- Ok(Self {
+impl From<BasicAuth> for BasicAuthParams {
+ fn from(auth: BasicAuth) -> Self {
+ Self {
username: auth.user_id().to_string(),
password: auth.password().unwrap_or(&"".into()).to_string(),
- })
+ }
}
}
@@ -74,47 +69,24 @@ pub fn get_hash<T: Digest>(text: &str) -> Vec<u8> {
hasher.update(text);
hasher.finalize().to_vec()
}
+
pub struct CurrentUser {
pub name: String,
}
-fn handle_auth(req: &HttpRequest) -> Result<(), ContextualError> {
+pub async fn handle_auth(
+ req: ServiceRequest,
+ cred: BasicAuth,
+) -> actix_web::Result<ServiceRequest> {
let required_auth = &req.app_data::<crate::MiniserveConfig>().unwrap().auth;
- if required_auth.is_empty() {
- // auth is disabled by configuration
- return Ok(());
- }
-
- match BasicAuthParams::try_from_request(req) {
- Ok(cred) => match match_auth(&cred, required_auth) {
- true => {
- req.extensions_mut().insert(CurrentUser {
- name: cred.username,
- });
- Ok(())
- }
- false => Err(ContextualError::InvalidHttpCredentials),
- },
- Err(_) => Err(ContextualError::RequireHttpCredentials),
- }
-}
+ req.extensions_mut().insert(CurrentUser {
+ name: cred.user_id().to_string(),
+ });
-pub fn auth_middleware<S>(
- mut req: ServiceRequest,
- srv: &S,
-) -> impl Future<Output = actix_web::Result<ServiceResponse>> + 'static
-where
- S: Service<ServiceRequest, Response = ServiceResponse, Error = actix_web::Error>,
- S::Future: 'static,
-{
- match handle_auth(req.parts_mut().0) {
- Ok(_) => Either::Left(srv.call(req)),
- Err(err) => {
- let resp = req.into_response(err.error_response());
- Either::Right(ready(Ok(resp)))
- }
- }
+ match_auth(&cred.into(), required_auth)
+ .then(|| req)
+ .ok_or_else(|| ContextualError::InvalidHttpCredentials.into())
}
#[rustfmt::skip]
diff --git a/src/errors.rs b/src/errors.rs
index 25d0529..c6fcce3 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -58,10 +58,6 @@ pub enum ContextualError {
#[error("{0}")]
ArchiveCreationDetailError(String),
- /// Might occur when the HTTP credentials are not provided
- #[error("Access requires HTTP authentication")]
- RequireHttpCredentials,
-
/// Might occur when the HTTP credentials are not correct
#[error("Invalid credentials for HTTP authentication")]
InvalidHttpCredentials,
@@ -90,20 +86,17 @@ impl ResponseError for ContextualError {
Self::ArchiveCreationError(_, err) => err.status_code(),
Self::RouteNotFoundError(_) => StatusCode::NOT_FOUND,
Self::InsufficientPermissionsError(_) => StatusCode::FORBIDDEN,
- Self::InvalidHttpCredentials | Self::RequireHttpCredentials => StatusCode::UNAUTHORIZED,
+ Self::InvalidHttpCredentials => StatusCode::UNAUTHORIZED,
Self::InvalidHttpRequestError(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn error_response(&self) -> HttpResponse {
- if let Self::RequireHttpCredentials = self {
- } else {
- log_error_chain(self.to_string());
- }
+ log_error_chain(self.to_string());
let mut resp = HttpResponse::build(self.status_code());
- if let Self::RequireHttpCredentials | Self::InvalidHttpCredentials = self {
+ if let Self::InvalidHttpCredentials = self {
resp.append_header((
header::WWW_AUTHENTICATE,
header::HeaderValue::from_static("Basic realm=\"miniserve\""),
diff --git a/src/main.rs b/src/main.rs
index eb159a2..205fac5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,10 +9,10 @@ use actix_files::NamedFile;
use actix_web::web;
use actix_web::{http::header::ContentType, Responder};
use actix_web::{middleware, App, HttpRequest, HttpResponse};
-use anyhow::{bail, Result};
-use clap::{crate_version, Clap, IntoApp};
-use clap_generate::generators::{Bash, Elvish, Fish, PowerShell, Zsh};
-use clap_generate::{generate, Shell};
+use actix_web_httpauth::middleware::HttpAuthentication;
+use anyhow::Result;
+use clap::{crate_version, IntoApp, Parser};
+use clap_generate::generate;
use log::{error, warn};
use qrcodegen::{QrCode, QrCodeEcc};
use yansi::{Color, Paint};
@@ -35,18 +35,8 @@ fn main() -> Result<()> {
if let Some(shell) = args.print_completions {
let mut clap_app = args::CliArgs::into_app();
- match shell {
- Shell::Bash => generate::<Bash, _>(&mut clap_app, "miniserve", &mut std::io::stdout()),
- Shell::Elvish => {
- generate::<Elvish, _>(&mut clap_app, "miniserve", &mut std::io::stdout())
- }
- Shell::Fish => generate::<Fish, _>(&mut clap_app, "miniserve", &mut std::io::stdout()),
- Shell::PowerShell => {
- generate::<PowerShell, _>(&mut clap_app, "miniserve", &mut std::io::stdout())
- }
- Shell::Zsh => generate::<Zsh, _>(&mut clap_app, "miniserve", &mut std::io::stdout()),
- _ => bail!("Invalid shell provided!"),
- }
+ let app_name = clap_app.get_name().to_string();
+ generate(shell, &mut clap_app, app_name, &mut io::stdout());
return Ok(());
}
@@ -207,11 +197,10 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
.route(&format!("/{}", inside_config.css_route), web::get().to(css))
.service(
web::scope(inside_config.random_route.as_deref().unwrap_or(""))
- // we should use `actix_web_httpauth::middleware::HttpAuthentication`
- // but it is unfortuantrly broken
- // see: https://github.com/actix/actix-extras/issues/127
- // TODO replace this when fixed upstream
- .wrap_fn(auth::auth_middleware)
+ .wrap(middleware::Condition::new(
+ !inside_config.auth.is_empty(),
+ HttpAuthentication::basic(auth::handle_auth),
+ ))
.configure(|c| configure_app(c, &inside_config)),
)
.default_service(web::get().to(error_404))
diff --git a/tests/cli.rs b/tests/cli.rs
index 8c88c93..7c3c972 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -32,10 +32,10 @@ fn version_shows() -> Result<(), Error> {
#[test]
/// Print completions and exit.
fn print_completions() -> Result<(), Error> {
- for shell in &Shell::variants() {
+ for shell in Shell::arg_values() {
Command::cargo_bin("miniserve")?
.arg("--print-completions")
- .arg(&shell)
+ .arg(shell.get_name())
.assert()
.success();
}