feat: add validate_command_access.sh with its tests
This commit is contained in:
parent
ba052d78d4
commit
e6fff0c044
47
tests/test_validate_command_access.sh
Executable file
47
tests/test_validate_command_access.sh
Executable file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cat >access.yml <<EOF
|
||||
pallav:
|
||||
fixedArgsCommands:
|
||||
build:
|
||||
- base
|
||||
- workspace
|
||||
- all
|
||||
clean:
|
||||
status:
|
||||
multiArgsCommands:
|
||||
remove:
|
||||
- palak
|
||||
- param
|
||||
- darshan
|
||||
EOF
|
||||
|
||||
source ./validate_command_access.sh
|
||||
|
||||
testcase() {
|
||||
local desc="$1"
|
||||
shift
|
||||
if validate_command pallav "$@"; then
|
||||
echo "PASS: $desc"
|
||||
else
|
||||
echo "FAIL: $desc"
|
||||
fi
|
||||
}
|
||||
|
||||
testcase "build base (valid)" build base
|
||||
testcase "build all (valid)" build all
|
||||
testcase "build base workspace (invalid)" build base workspace || true
|
||||
testcase "build (no arg, invalid)" build || true
|
||||
testcase "clean (zero-arg, valid)" clean
|
||||
testcase "clean with arg (invalid)" clean foo || true
|
||||
|
||||
testcase "remove palak (valid)" remove palak
|
||||
testcase "remove param palak (valid, any order)" remove param palak
|
||||
testcase "remove palak param darshan (valid, any order)" remove palak param darshan
|
||||
testcase "remove (no arg, invalid)" remove || true
|
||||
testcase "remove foo (invalid)" remove foo || true
|
||||
testcase "remove palak palak (duplicate, invalid)" remove palak palak || true
|
||||
|
||||
testcase "status (zero-arg, valid)" status
|
||||
testcase "status foo (invalid)" status foo || true
|
83
validate_command_access.sh
Normal file
83
validate_command_access.sh
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
validate_command() {
|
||||
local PERSON="$1"
|
||||
local cmd="$2"
|
||||
shift 2
|
||||
local tokens=("$@")
|
||||
local yaml="access.yml"
|
||||
|
||||
# Check if fixedArgsCommands.<cmd> exists
|
||||
local is_fixed
|
||||
is_fixed="$(yq e ".\"$PERSON\".fixedArgsCommands | has(\"$cmd\")" "$yaml")"
|
||||
# Check if multiArgsCommands.<cmd> exists
|
||||
local is_multi
|
||||
is_multi="$(yq e ".\"$PERSON\".multiArgsCommands | has(\"$cmd\")" "$yaml")"
|
||||
|
||||
if [[ "$is_fixed" != "true" && "$is_multi" != "true" ]]; then
|
||||
echo "ERROR: Command '$cmd' not allowed for $PERSON" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Exclude flags from positional args
|
||||
local args=()
|
||||
for tok in "${tokens[@]}"; do
|
||||
[[ "$tok" == -* ]] && continue
|
||||
args+=("$tok")
|
||||
done
|
||||
|
||||
if [[ "$is_fixed" == "true" ]]; then
|
||||
mapfile -t allowed < <(yq e ".\"$PERSON\".fixedArgsCommands.\"$cmd\"[]" "$yaml" 2>/dev/null)
|
||||
local n_allowed="${#allowed[@]}"
|
||||
if [[ $n_allowed -eq 0 ]]; then
|
||||
# zero-arg command
|
||||
if [[ ${#args[@]} -ne 0 ]]; then
|
||||
echo "ERROR: Command '$cmd' takes no arguments" >&2
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
# depth is 1: only one of the allowed choices must be present
|
||||
if [[ ${#args[@]} -ne 1 ]]; then
|
||||
echo "ERROR: Command '$cmd' requires exactly 1 argument: (${allowed[*]})" >&2
|
||||
return 1
|
||||
fi
|
||||
local found=0
|
||||
for want in "${allowed[@]}"; do
|
||||
[[ "${args[0]}" == "$want" ]] && found=1 && break
|
||||
done
|
||||
if [[ $found -eq 0 ]]; then
|
||||
echo "ERROR: Invalid argument '${args[0]}' for '$cmd'; allowed: (${allowed[*]})" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$is_multi" == "true" ]]; then
|
||||
mapfile -t allowed < <(yq e ".\"$PERSON\".multiArgsCommands.\"$cmd\"[]" "$yaml" 2>/dev/null)
|
||||
local n_allowed="${#allowed[@]}"
|
||||
if [[ ${#args[@]} -lt 1 || ${#args[@]} -gt $n_allowed ]]; then
|
||||
echo "ERROR: Command '$cmd' requires 1 to $n_allowed arguments: (${allowed[*]})" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Order doesn't matter, but all must be unique and from allowed.
|
||||
# Build a set of allowed args.
|
||||
declare -A allowed_set=()
|
||||
for want in "${allowed[@]}"; do allowed_set["$want"]=1; done
|
||||
|
||||
declare -A seen=()
|
||||
for a in "${args[@]}"; do
|
||||
[[ -z "${allowed_set[$a]}" ]] && {
|
||||
echo "ERROR: Invalid argument '$a' for '$cmd'; allowed: (${allowed[*]})" >&2
|
||||
return 1
|
||||
}
|
||||
[[ -n "${seen[$a]}" ]] && {
|
||||
echo "ERROR: Duplicate argument '$a' for '$cmd'" >&2
|
||||
return 1
|
||||
}
|
||||
seen["$a"]=1
|
||||
done
|
||||
return 0
|
||||
fi
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user