Add --account N flag and fix credential priority in sh/lua/pl/tcl
When --account N is passed, it should bypass env vars and load accounts.csv row N directly. Previously, env vars were checked first so the explicit --account flag had no effect when UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY were set. Correct credential priority (all 4 files): 1. Explicit -p/-k key flags 2. --account N → direct CSV row lookup (bypasses env vars) 3. UNSANDBOX_PUBLIC_KEY / UNSANDBOX_SECRET_KEY env vars 4. ~/.unsandbox/accounts.csv default (row 0) 5. ./accounts.csv default (row 0) Files updated: un.sh (bash), un.lua, un.pl (perl), un.tcl Also fixes load_accounts_csv in sh and tcl to support reading an arbitrary row index rather than always returning the first line.
This commit is contained in:
parent
ed6c52b001
commit
ce327b35e9
4 changed files with 137 additions and 19 deletions
|
|
@ -21,6 +21,7 @@ VERSION="4.2.50"
|
||||||
API_BASE="https://api.unsandbox.com"
|
API_BASE="https://api.unsandbox.com"
|
||||||
PORTAL_BASE="https://unsandbox.com"
|
PORTAL_BASE="https://unsandbox.com"
|
||||||
LAST_ERROR=""
|
LAST_ERROR=""
|
||||||
|
ACCOUNT_INDEX=-1
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
BLUE='\033[34m'
|
BLUE='\033[34m'
|
||||||
|
|
@ -104,8 +105,19 @@ hmac_sign() {
|
||||||
|
|
||||||
load_accounts_csv() {
|
load_accounts_csv() {
|
||||||
local path="${1:-$HOME/.unsandbox/accounts.csv}"
|
local path="${1:-$HOME/.unsandbox/accounts.csv}"
|
||||||
|
local row="${2:-0}"
|
||||||
[ -f "$path" ] || return 1
|
[ -f "$path" ] || return 1
|
||||||
head -1 "$path" 2>/dev/null | grep -v '^#'
|
local n=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[[ "$line" =~ ^# ]] && continue
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
if [ "$n" -eq "$row" ]; then
|
||||||
|
echo "$line"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
n=$((n + 1))
|
||||||
|
done < "$path"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
get_credentials() {
|
get_credentials() {
|
||||||
|
|
@ -115,7 +127,20 @@ get_credentials() {
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Tier 2: Environment
|
# Tier 2: --account N flag → bypass env vars, load CSV row N directly
|
||||||
|
if [ "$ACCOUNT_INDEX" -ge 0 ] 2>/dev/null; then
|
||||||
|
local creds
|
||||||
|
creds=$(load_accounts_csv "$HOME/.unsandbox/accounts.csv" "$ACCOUNT_INDEX" 2>/dev/null || true)
|
||||||
|
[ -z "$creds" ] && creds=$(load_accounts_csv "./accounts.csv" "$ACCOUNT_INDEX" 2>/dev/null || true)
|
||||||
|
if [ -n "$creds" ]; then
|
||||||
|
echo "$creds"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
set_error "Account index $ACCOUNT_INDEX not found in accounts.csv"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tier 3: Environment
|
||||||
if [ -n "${UNSANDBOX_PUBLIC_KEY:-}" ] && [ -n "${UNSANDBOX_SECRET_KEY:-}" ]; then
|
if [ -n "${UNSANDBOX_PUBLIC_KEY:-}" ] && [ -n "${UNSANDBOX_SECRET_KEY:-}" ]; then
|
||||||
echo "$UNSANDBOX_PUBLIC_KEY:$UNSANDBOX_SECRET_KEY"
|
echo "$UNSANDBOX_PUBLIC_KEY:$UNSANDBOX_SECRET_KEY"
|
||||||
return
|
return
|
||||||
|
|
@ -127,7 +152,7 @@ get_credentials() {
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Tier 3: Home directory
|
# Tier 4: Home directory
|
||||||
local creds
|
local creds
|
||||||
creds=$(load_accounts_csv "$HOME/.unsandbox/accounts.csv" 2>/dev/null || true)
|
creds=$(load_accounts_csv "$HOME/.unsandbox/accounts.csv" 2>/dev/null || true)
|
||||||
if [ -n "$creds" ]; then
|
if [ -n "$creds" ]; then
|
||||||
|
|
@ -135,7 +160,7 @@ get_credentials() {
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Tier 4: Local directory
|
# Tier 5: Local directory
|
||||||
creds=$(load_accounts_csv "./accounts.csv" 2>/dev/null || true)
|
creds=$(load_accounts_csv "./accounts.csv" 2>/dev/null || true)
|
||||||
if [ -n "$creds" ]; then
|
if [ -n "$creds" ]; then
|
||||||
echo "$creds"
|
echo "$creds"
|
||||||
|
|
@ -1230,6 +1255,21 @@ if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Pre-scan for --account N before dispatching
|
||||||
|
_args=("$@")
|
||||||
|
_new_args=()
|
||||||
|
_i=0
|
||||||
|
while [ $_i -lt ${#_args[@]} ]; do
|
||||||
|
if [ "${_args[$_i]}" = "--account" ]; then
|
||||||
|
_i=$((_i + 1))
|
||||||
|
ACCOUNT_INDEX="${_args[$_i]}"
|
||||||
|
else
|
||||||
|
_new_args+=("${_args[$_i]}")
|
||||||
|
fi
|
||||||
|
_i=$((_i + 1))
|
||||||
|
done
|
||||||
|
set -- "${_new_args[@]+"${_new_args[@]}"}"
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
languages)
|
languages)
|
||||||
shift
|
shift
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ Un.API_BASE = "https://api.unsandbox.com"
|
||||||
Un.PORTAL_BASE = "https://unsandbox.com"
|
Un.PORTAL_BASE = "https://unsandbox.com"
|
||||||
Un.VERSION = "4.3.4"
|
Un.VERSION = "4.3.4"
|
||||||
Un.LAST_ERROR = ""
|
Un.LAST_ERROR = ""
|
||||||
|
Un.ACCOUNT_INDEX = -1 -- -1 means not set; set to N to use accounts.csv row N
|
||||||
|
|
||||||
-- Colors
|
-- Colors
|
||||||
local BLUE = "\027[34m"
|
local BLUE = "\027[34m"
|
||||||
|
|
@ -116,7 +117,20 @@ function Un.get_credentials(opts)
|
||||||
return opts.public_key, opts.secret_key
|
return opts.public_key, opts.secret_key
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Tier 2: Environment
|
-- Tier 2: --account N flag → bypass env vars, load CSV row N directly
|
||||||
|
local ai = opts.account_index
|
||||||
|
if (ai == nil) and Un.ACCOUNT_INDEX >= 0 then ai = Un.ACCOUNT_INDEX end
|
||||||
|
if ai and ai >= 0 then
|
||||||
|
local row = ai + 1 -- Lua tables are 1-indexed
|
||||||
|
local accounts = Un.load_accounts_csv()
|
||||||
|
if #accounts >= row then return accounts[row][1], accounts[row][2] end
|
||||||
|
accounts = Un.load_accounts_csv("./accounts.csv")
|
||||||
|
if #accounts >= row then return accounts[row][1], accounts[row][2] end
|
||||||
|
Un.set_error("Account index " .. ai .. " not found in accounts.csv")
|
||||||
|
return nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Tier 3: Environment
|
||||||
local pk = os.getenv("UNSANDBOX_PUBLIC_KEY")
|
local pk = os.getenv("UNSANDBOX_PUBLIC_KEY")
|
||||||
local sk = os.getenv("UNSANDBOX_SECRET_KEY")
|
local sk = os.getenv("UNSANDBOX_SECRET_KEY")
|
||||||
if pk and sk then return pk, sk end
|
if pk and sk then return pk, sk end
|
||||||
|
|
@ -126,11 +140,11 @@ function Un.get_credentials(opts)
|
||||||
return os.getenv("UNSANDBOX_API_KEY"), ""
|
return os.getenv("UNSANDBOX_API_KEY"), ""
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Tier 3: Home directory
|
-- Tier 4: Home directory
|
||||||
local accounts = Un.load_accounts_csv()
|
local accounts = Un.load_accounts_csv()
|
||||||
if #accounts > 0 then return accounts[1][1], accounts[1][2] end
|
if #accounts > 0 then return accounts[1][1], accounts[1][2] end
|
||||||
|
|
||||||
-- Tier 4: Local directory
|
-- Tier 5: Local directory
|
||||||
accounts = Un.load_accounts_csv("./accounts.csv")
|
accounts = Un.load_accounts_csv("./accounts.csv")
|
||||||
if #accounts > 0 then return accounts[1][1], accounts[1][2] end
|
if #accounts > 0 then return accounts[1][1], accounts[1][2] end
|
||||||
|
|
||||||
|
|
@ -744,6 +758,21 @@ if arg and arg[0] then
|
||||||
local args = arg
|
local args = arg
|
||||||
local i = 1
|
local i = 1
|
||||||
|
|
||||||
|
-- Pre-scan for --account N; strip it from args before dispatch
|
||||||
|
local _filtered = {}
|
||||||
|
local _j = 1
|
||||||
|
while _j <= #args do
|
||||||
|
if args[_j] == "--account" then
|
||||||
|
_j = _j + 1
|
||||||
|
Un.ACCOUNT_INDEX = tonumber(args[_j]) or -1
|
||||||
|
else
|
||||||
|
table.insert(_filtered, args[_j])
|
||||||
|
end
|
||||||
|
_j = _j + 1
|
||||||
|
end
|
||||||
|
for k = 1, #_filtered do args[k] = _filtered[k] end
|
||||||
|
for k = #_filtered + 1, #args do args[k] = nil end
|
||||||
|
|
||||||
if #args == 0 then
|
if #args == 0 then
|
||||||
print("Usage: lua un.lua [options] <source_file>")
|
print("Usage: lua un.lua [options] <source_file>")
|
||||||
print(" lua un.lua -s <language> '<code>'")
|
print(" lua un.lua -s <language> '<code>'")
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ our $PORTAL_BASE = 'https://unsandbox.com';
|
||||||
|
|
||||||
# Thread-local error storage
|
# Thread-local error storage
|
||||||
our $LAST_ERROR = "";
|
our $LAST_ERROR = "";
|
||||||
|
our $ACCOUNT_INDEX = -1; # -1 means not set; set to N to use accounts.csv row N
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
my $BLUE = "\033[34m";
|
my $BLUE = "\033[34m";
|
||||||
|
|
@ -122,7 +123,18 @@ sub get_credentials {
|
||||||
# Tier 1: Arguments
|
# Tier 1: Arguments
|
||||||
return ($opts{public_key}, $opts{secret_key}) if $opts{public_key} && $opts{secret_key};
|
return ($opts{public_key}, $opts{secret_key}) if $opts{public_key} && $opts{secret_key};
|
||||||
|
|
||||||
# Tier 2: Environment
|
# Tier 2: --account N flag → bypass env vars, load CSV row N directly
|
||||||
|
my $ai = exists $opts{account_index} ? $opts{account_index} : $Un::ACCOUNT_INDEX;
|
||||||
|
if (defined $ai && $ai >= 0) {
|
||||||
|
my $home_accounts = load_accounts_csv();
|
||||||
|
return @{$home_accounts->[$ai]} if @$home_accounts > $ai;
|
||||||
|
my $local_accounts = load_accounts_csv("./accounts.csv");
|
||||||
|
return @{$local_accounts->[$ai]} if @$local_accounts > $ai;
|
||||||
|
set_error("Account index $ai not found in accounts.csv");
|
||||||
|
return (undef, undef);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tier 3: Environment
|
||||||
if ($ENV{UNSANDBOX_PUBLIC_KEY} && $ENV{UNSANDBOX_SECRET_KEY}) {
|
if ($ENV{UNSANDBOX_PUBLIC_KEY} && $ENV{UNSANDBOX_SECRET_KEY}) {
|
||||||
return ($ENV{UNSANDBOX_PUBLIC_KEY}, $ENV{UNSANDBOX_SECRET_KEY});
|
return ($ENV{UNSANDBOX_PUBLIC_KEY}, $ENV{UNSANDBOX_SECRET_KEY});
|
||||||
}
|
}
|
||||||
|
|
@ -132,11 +144,11 @@ sub get_credentials {
|
||||||
return ($ENV{UNSANDBOX_API_KEY}, '');
|
return ($ENV{UNSANDBOX_API_KEY}, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
# Tier 3: Home directory
|
# Tier 4: Home directory
|
||||||
my $home_accounts = load_accounts_csv();
|
my $home_accounts = load_accounts_csv();
|
||||||
return @{$home_accounts->[0]} if @$home_accounts;
|
return @{$home_accounts->[0]} if @$home_accounts;
|
||||||
|
|
||||||
# Tier 4: Local directory
|
# Tier 5: Local directory
|
||||||
my $local_accounts = load_accounts_csv("./accounts.csv");
|
my $local_accounts = load_accounts_csv("./accounts.csv");
|
||||||
return @{$local_accounts->[0]} if @$local_accounts;
|
return @{$local_accounts->[0]} if @$local_accounts;
|
||||||
|
|
||||||
|
|
@ -1541,6 +1553,8 @@ sub main {
|
||||||
} elsif ($arg eq 'env' && $options{command} && $options{command} eq 'service') {
|
} elsif ($arg eq 'env' && $options{command} && $options{command} eq 'service') {
|
||||||
$options{env_action} = $ARGV[++$i];
|
$options{env_action} = $ARGV[++$i];
|
||||||
$options{env_target} = $ARGV[++$i] if defined $ARGV[$i+1] && $ARGV[$i+1] !~ /^-/;
|
$options{env_target} = $ARGV[++$i] if defined $ARGV[$i+1] && $ARGV[$i+1] !~ /^-/;
|
||||||
|
} elsif ($arg eq '--account') {
|
||||||
|
$Un::ACCOUNT_INDEX = int($ARGV[++$i]);
|
||||||
} elsif ($arg eq '--help' || $arg eq '-h') {
|
} elsif ($arg eq '--help' || $arg eq '-h') {
|
||||||
show_help();
|
show_help();
|
||||||
} elsif ($arg =~ /^-/) {
|
} elsif ($arg =~ /^-/) {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ namespace eval Un {
|
||||||
variable LANGUAGES_CACHE_TTL 3600
|
variable LANGUAGES_CACHE_TTL 3600
|
||||||
variable LANGUAGES_CACHE_FILE [file join $::env(HOME) ".unsandbox" "languages.json"]
|
variable LANGUAGES_CACHE_FILE [file join $::env(HOME) ".unsandbox" "languages.json"]
|
||||||
variable LAST_ERROR ""
|
variable LAST_ERROR ""
|
||||||
|
variable ACCOUNT_INDEX -1
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
variable BLUE "\033\[34m"
|
variable BLUE "\033\[34m"
|
||||||
|
|
@ -109,22 +110,43 @@ namespace eval Un {
|
||||||
# Credential Management
|
# Credential Management
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
proc load_accounts_csv {path} {
|
proc load_accounts_csv {path {row 0}} {
|
||||||
if {![file exists $path]} { return "" }
|
if {![file exists $path]} { return "" }
|
||||||
if {[catch {open $path r} fp]} { return "" }
|
if {[catch {open $path r} fp]} { return "" }
|
||||||
set line [gets $fp]
|
set n 0
|
||||||
|
set result ""
|
||||||
|
while {[gets $fp line] >= 0} {
|
||||||
|
if {[string index $line 0] eq "#" || [string trim $line] eq ""} { continue }
|
||||||
|
if {$n == $row} { set result $line; break }
|
||||||
|
incr n
|
||||||
|
}
|
||||||
close $fp
|
close $fp
|
||||||
if {[string index $line 0] eq "#"} { return "" }
|
return $result
|
||||||
return $line
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc get_credentials {{public_key ""} {secret_key ""}} {
|
proc get_credentials {{public_key ""} {secret_key ""} {account_index -1}} {
|
||||||
|
variable ACCOUNT_INDEX
|
||||||
|
|
||||||
# Tier 1: Arguments
|
# Tier 1: Arguments
|
||||||
if {$public_key ne "" && $secret_key ne ""} {
|
if {$public_key ne "" && $secret_key ne ""} {
|
||||||
return [list $public_key $secret_key]
|
return [list $public_key $secret_key]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Tier 2: Environment
|
# Tier 2: --account N flag → bypass env vars, load CSV row N directly
|
||||||
|
set ai $account_index
|
||||||
|
if {$ai < 0} { set ai $ACCOUNT_INDEX }
|
||||||
|
if {$ai >= 0} {
|
||||||
|
set creds [load_accounts_csv [file join $::env(HOME) ".unsandbox" "accounts.csv"] $ai]
|
||||||
|
if {$creds eq ""} { set creds [load_accounts_csv "./accounts.csv" $ai] }
|
||||||
|
if {$creds ne ""} {
|
||||||
|
set parts [split $creds ","]
|
||||||
|
return [list [lindex $parts 0] [lindex $parts 1]]
|
||||||
|
}
|
||||||
|
set_error "Account index $ai not found in accounts.csv"
|
||||||
|
error "Account index $ai not found in accounts.csv"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tier 3: Environment
|
||||||
if {[info exists ::env(UNSANDBOX_PUBLIC_KEY)] && [info exists ::env(UNSANDBOX_SECRET_KEY)]} {
|
if {[info exists ::env(UNSANDBOX_PUBLIC_KEY)] && [info exists ::env(UNSANDBOX_SECRET_KEY)]} {
|
||||||
return [list $::env(UNSANDBOX_PUBLIC_KEY) $::env(UNSANDBOX_SECRET_KEY)]
|
return [list $::env(UNSANDBOX_PUBLIC_KEY) $::env(UNSANDBOX_SECRET_KEY)]
|
||||||
}
|
}
|
||||||
|
|
@ -134,14 +156,14 @@ namespace eval Un {
|
||||||
return [list $::env(UNSANDBOX_API_KEY) ""]
|
return [list $::env(UNSANDBOX_API_KEY) ""]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Tier 3: Home directory
|
# Tier 4: Home directory
|
||||||
set creds [load_accounts_csv [file join $::env(HOME) ".unsandbox" "accounts.csv"]]
|
set creds [load_accounts_csv [file join $::env(HOME) ".unsandbox" "accounts.csv"]]
|
||||||
if {$creds ne ""} {
|
if {$creds ne ""} {
|
||||||
set parts [split $creds ","]
|
set parts [split $creds ","]
|
||||||
return [list [lindex $parts 0] [lindex $parts 1]]
|
return [list [lindex $parts 0] [lindex $parts 1]]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Tier 4: Local directory
|
# Tier 5: Local directory
|
||||||
set creds [load_accounts_csv "./accounts.csv"]
|
set creds [load_accounts_csv "./accounts.csv"]
|
||||||
if {$creds ne ""} {
|
if {$creds ne ""} {
|
||||||
set parts [split $creds ","]
|
set parts [split $creds ","]
|
||||||
|
|
@ -1030,7 +1052,20 @@ Environment:
|
||||||
}
|
}
|
||||||
|
|
||||||
proc main {argv} {
|
proc main {argv} {
|
||||||
variable BLUE RED RESET
|
variable BLUE RED RESET ACCOUNT_INDEX
|
||||||
|
|
||||||
|
# Pre-scan for --account N; strip it from argv before dispatch
|
||||||
|
set filtered {}
|
||||||
|
for {set i 0} {$i < [llength $argv]} {incr i} {
|
||||||
|
set a [lindex $argv $i]
|
||||||
|
if {$a eq "--account"} {
|
||||||
|
incr i
|
||||||
|
set ACCOUNT_INDEX [lindex $argv $i]
|
||||||
|
} else {
|
||||||
|
lappend filtered $a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set argv $filtered
|
||||||
|
|
||||||
if {[llength $argv] == 0} {
|
if {[llength $argv] == 0} {
|
||||||
show_help
|
show_help
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue