add route min/max arg restrictions
This commit is contained in:
parent
7585687710
commit
0df0c60013
3 changed files with 84 additions and 10 deletions
|
@ -67,7 +67,7 @@ impl<'de> Deserialize<'de> for Route {
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(field_identifier, rename_all = "lowercase")]
|
#[serde(field_identifier, rename_all = "snake_case")]
|
||||||
enum Field {
|
enum Field {
|
||||||
Path,
|
Path,
|
||||||
Hidden,
|
Hidden,
|
||||||
|
|
|
@ -66,6 +66,7 @@ async fn run() -> Result<(), BunBunError> {
|
||||||
groups: conf.groups,
|
groups: conf.groups,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Cannot be named _ or Rust will immediately drop it.
|
||||||
let _watch = start_watch(Arc::clone(&state), conf_data, opts.large_config)?;
|
let _watch = start_watch(Arc::clone(&state), conf_data, opts.large_config)?;
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
|
|
|
@ -158,29 +158,51 @@ fn resolve_hop<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if maybe_route.is_some() {
|
let args = split_args.collect::<Vec<_>>();
|
||||||
split_args.next();
|
let arg_count = args.len();
|
||||||
}
|
|
||||||
|
|
||||||
let args = split_args.collect::<Vec<_>>().join(" ");
|
|
||||||
|
|
||||||
// Try resolving with a matched command
|
// Try resolving with a matched command
|
||||||
if let Some(route) = maybe_route {
|
if let Some(route) = maybe_route {
|
||||||
debug!("Resolved {} with args {}", route, args);
|
let args = if args.is_empty() { &[] } else { &args[1..] }.join(" ");
|
||||||
return RouteResolution::Resolved { route, args };
|
let arg_count = arg_count - 1;
|
||||||
|
if check_route(route, arg_count) {
|
||||||
|
debug!("Resolved {} with args {}", route, args);
|
||||||
|
return RouteResolution::Resolved { route, args };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try resolving with the default route, if it exists
|
// Try resolving with the default route, if it exists
|
||||||
if let Some(route) = default_route {
|
if let Some(route) = default_route {
|
||||||
if let Some(route) = routes.get(route) {
|
if let Some(route) = routes.get(route) {
|
||||||
debug!("Using default route {} with args {}", route, args);
|
if check_route(route, arg_count) {
|
||||||
return RouteResolution::Resolved { route, args };
|
let args = args.join(" ");
|
||||||
|
debug!("Using default route {} with args {}", route, args);
|
||||||
|
return RouteResolution::Resolved { route, args };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RouteResolution::Unresolved
|
RouteResolution::Unresolved
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the user provided string has the correct properties required by
|
||||||
|
/// the route to be successfully matched.
|
||||||
|
fn check_route(route: &Route, arg_count: usize) -> bool {
|
||||||
|
if let Some(min_args) = route.min_args {
|
||||||
|
if arg_count < min_args {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(max_args) = route.max_args {
|
||||||
|
if arg_count > max_args {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Runs the executable with the user's input as a single argument. Returns Ok
|
/// Runs the executable with the user's input as a single argument. Returns Ok
|
||||||
/// so long as the executable was successfully executed. Returns an Error if the
|
/// so long as the executable was successfully executed. Returns an Error if the
|
||||||
/// file doesn't exist or bunbun did not have permission to read and execute the
|
/// file doesn't exist or bunbun did not have permission to read and execute the
|
||||||
|
@ -284,6 +306,57 @@ mod resolve_hop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod check_route {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn create_route(
|
||||||
|
min_args: impl Into<Option<usize>>,
|
||||||
|
max_args: impl Into<Option<usize>>,
|
||||||
|
) -> Route {
|
||||||
|
Route {
|
||||||
|
description: None,
|
||||||
|
hidden: false,
|
||||||
|
max_args: max_args.into(),
|
||||||
|
min_args: min_args.into(),
|
||||||
|
path: String::new(),
|
||||||
|
route_type: RouteType::External,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_min_arg_no_max_arg_counts() {
|
||||||
|
assert!(check_route(&create_route(None, None), 0));
|
||||||
|
assert!(check_route(&create_route(None, None), usize::MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn min_arg_no_max_arg_counts() {
|
||||||
|
assert!(!check_route(&create_route(3, None), 0));
|
||||||
|
assert!(!check_route(&create_route(3, None), 2));
|
||||||
|
assert!(check_route(&create_route(3, None), 3));
|
||||||
|
assert!(check_route(&create_route(3, None), 4));
|
||||||
|
assert!(check_route(&create_route(3, None), usize::MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_min_arg_max_arg_counts() {
|
||||||
|
assert!(check_route(&create_route(None, 3), 0));
|
||||||
|
assert!(check_route(&create_route(None, 3), 2));
|
||||||
|
assert!(check_route(&create_route(None, 3), 3));
|
||||||
|
assert!(!check_route(&create_route(None, 3), 4));
|
||||||
|
assert!(!check_route(&create_route(None, 3), usize::MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn min_arg_max_arg_counts() {
|
||||||
|
assert!(!check_route(&create_route(2, 3), 1));
|
||||||
|
assert!(check_route(&create_route(2, 3), 2));
|
||||||
|
assert!(check_route(&create_route(2, 3), 3));
|
||||||
|
assert!(!check_route(&create_route(2, 3), 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod resolve_path {
|
mod resolve_path {
|
||||||
use super::resolve_path;
|
use super::resolve_path;
|
||||||
|
|
Loading…
Reference in a new issue