tests
This commit is contained in:
234
tests/admin_test.sh
Executable file
234
tests/admin_test.sh
Executable file
@@ -0,0 +1,234 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Ginxsom Admin API Test Script
|
||||
# Tests admin API endpoints using nak (for Nostr events) and curl
|
||||
#
|
||||
# Prerequisites:
|
||||
# - nak: https://github.com/fiatjaf/nak
|
||||
# - curl
|
||||
# - jq (for JSON parsing)
|
||||
# - Admin pubkey configured in ginxsom server_config
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
GINXSOM_URL="http://localhost:9001"
|
||||
|
||||
# Test admin keys (for development/testing only - DO NOT USE IN PRODUCTION)
|
||||
TEST_ADMIN_PRIVKEY="993bf9c54fc00bd32a5a1ce64b6d384a5fce109df1e9aee9be1052c1e5cd8120"
|
||||
TEST_ADMIN_PUBKEY="2ef05348f28d24e0f0ed0751278442c27b62c823c37af8d8d89d8592c6ee84e7"
|
||||
|
||||
ADMIN_PRIVKEY="${ADMIN_PRIVKEY:-${TEST_ADMIN_PRIVKEY}}"
|
||||
ADMIN_PUBKEY=""
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Helper functions
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
log_info "Checking dependencies..."
|
||||
|
||||
for cmd in nak curl jq; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
log_error "$cmd is not installed"
|
||||
case $cmd in
|
||||
nak)
|
||||
echo "Install from: https://github.com/fiatjaf/nak"
|
||||
;;
|
||||
jq)
|
||||
echo "Install jq for JSON processing"
|
||||
;;
|
||||
curl)
|
||||
echo "curl should be available in most systems"
|
||||
;;
|
||||
esac
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
log_success "All dependencies found"
|
||||
}
|
||||
|
||||
generate_admin_keys() {
|
||||
if [[ -z "$ADMIN_PRIVKEY" ]]; then
|
||||
log_info "Generating new admin key pair..."
|
||||
ADMIN_PRIVKEY=$(nak key generate)
|
||||
log_warning "Generated new admin private key: $ADMIN_PRIVKEY"
|
||||
log_warning "Save this key for future use: export ADMIN_PRIVKEY='$ADMIN_PRIVKEY'"
|
||||
fi
|
||||
|
||||
ADMIN_PUBKEY=$(echo "$ADMIN_PRIVKEY" | nak key public)
|
||||
log_info "Admin public key: $ADMIN_PUBKEY"
|
||||
}
|
||||
|
||||
create_admin_event() {
|
||||
local method="$1"
|
||||
local content="admin_request"
|
||||
local expiration=$(($(date +%s) + 3600)) # 1 hour from now
|
||||
|
||||
# Create Nostr event with nak - always use "admin" tag for admin operations
|
||||
local event=$(nak event -k 24242 -c "$content" \
|
||||
--tag t="admin" \
|
||||
--tag expiration="$expiration" \
|
||||
--sec "$ADMIN_PRIVKEY")
|
||||
|
||||
echo "$event"
|
||||
}
|
||||
|
||||
send_admin_request() {
|
||||
local method="$1"
|
||||
local endpoint="$2"
|
||||
local data="$3"
|
||||
|
||||
log_info "Testing $method $endpoint"
|
||||
|
||||
# Create authenticated Nostr event
|
||||
local event=$(create_admin_event "$method")
|
||||
local auth_header="Nostr $(echo "$event" | base64 -w 0)"
|
||||
|
||||
# Send request with curl
|
||||
local curl_args=(-s -w "%{http_code}" -H "Authorization: $auth_header")
|
||||
|
||||
if [[ "$method" == "PUT" && -n "$data" ]]; then
|
||||
curl_args+=(-H "Content-Type: application/json" -d "$data")
|
||||
fi
|
||||
|
||||
local response=$(curl "${curl_args[@]}" -X "$method" "$GINXSOM_URL$endpoint")
|
||||
local http_code="${response: -3}"
|
||||
local body="${response%???}"
|
||||
|
||||
if [[ "$http_code" =~ ^2 ]]; then
|
||||
log_success "$method $endpoint - HTTP $http_code"
|
||||
if [[ -n "$body" ]]; then
|
||||
echo "$body" | jq . 2>/dev/null || echo "$body"
|
||||
fi
|
||||
else
|
||||
log_error "$method $endpoint - HTTP $http_code"
|
||||
echo "$body" | jq . 2>/dev/null || echo "$body"
|
||||
fi
|
||||
|
||||
return $([[ "$http_code" =~ ^2 ]])
|
||||
}
|
||||
|
||||
test_health_endpoint() {
|
||||
log_info "=== Testing Health Endpoint (no auth required) ==="
|
||||
|
||||
local response=$(curl -s -w "%{http_code}" "$GINXSOM_URL/api/health")
|
||||
local http_code="${response: -3}"
|
||||
local body="${response%???}"
|
||||
|
||||
if [[ "$http_code" =~ ^2 ]]; then
|
||||
log_success "GET /api/health - HTTP $http_code"
|
||||
echo "$body" | jq .
|
||||
else
|
||||
log_error "GET /api/health - HTTP $http_code"
|
||||
echo "$body"
|
||||
fi
|
||||
}
|
||||
|
||||
test_stats_endpoint() {
|
||||
log_info "=== Testing Statistics Endpoint ==="
|
||||
send_admin_request "GET" "/api/stats"
|
||||
}
|
||||
|
||||
test_config_endpoints() {
|
||||
log_info "=== Testing Configuration Endpoints ==="
|
||||
|
||||
# Get current config
|
||||
send_admin_request "GET" "/api/config"
|
||||
|
||||
# Update config
|
||||
local config_update='{
|
||||
"max_file_size": "209715200",
|
||||
"require_auth": "true",
|
||||
"nip94_enabled": "true"
|
||||
}'
|
||||
|
||||
send_admin_request "PUT" "/api/config" "$config_update"
|
||||
|
||||
# Get config again to verify
|
||||
send_admin_request "GET" "/api/config"
|
||||
}
|
||||
|
||||
test_files_endpoint() {
|
||||
log_info "=== Testing Files Endpoint ==="
|
||||
send_admin_request "GET" "/api/files?limit=10&offset=0"
|
||||
}
|
||||
|
||||
configure_server_admin() {
|
||||
log_warning "=== Server Configuration Required ==="
|
||||
log_warning "To use this admin interface, add the following to your ginxsom database:"
|
||||
log_warning ""
|
||||
log_warning "sqlite3 db/ginxsom.db << EOF"
|
||||
log_warning "INSERT OR REPLACE INTO server_config (key, value, description) VALUES"
|
||||
log_warning " ('admin_pubkey', '$ADMIN_PUBKEY', 'Nostr public key authorized for admin operations'),"
|
||||
log_warning " ('admin_enabled', 'true', 'Enable admin interface');"
|
||||
log_warning "EOF"
|
||||
log_warning ""
|
||||
log_warning "Then restart ginxsom server."
|
||||
|
||||
echo ""
|
||||
log_warning "Or use the Nak utility to interact with the API:"
|
||||
echo ""
|
||||
log_warning " # Create an event"
|
||||
echo " EVENT=\$(nak event -k 24242 -c 'admin_request' --tag t='GET' --tag expiration=\$(date -d '+1 hour' +%s) --sec '$ADMIN_PRIVKEY')"
|
||||
echo ""
|
||||
log_warning " # Send authenticated request"
|
||||
echo " curl -H \"Authorization: Nostr \$(echo \"\$EVENT\" | base64 -w 0)\" http://localhost:9001/api/stats"
|
||||
echo ""
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "=== Ginxsom Admin API Test Suite ==="
|
||||
echo ""
|
||||
|
||||
check_dependencies
|
||||
generate_admin_keys
|
||||
|
||||
# Setup admin configuration automatically
|
||||
echo ""
|
||||
log_info "Setting up admin configuration..."
|
||||
./tests/init_admin.sh
|
||||
echo ""
|
||||
|
||||
# Test endpoints
|
||||
test_health_endpoint
|
||||
echo ""
|
||||
|
||||
test_stats_endpoint
|
||||
echo ""
|
||||
|
||||
test_config_endpoints
|
||||
echo ""
|
||||
|
||||
test_files_endpoint
|
||||
echo ""
|
||||
|
||||
log_success "Admin API testing complete!"
|
||||
log_info "Admin pubkey for server config: $ADMIN_PUBKEY"
|
||||
}
|
||||
|
||||
# Allow sourcing for individual function testing
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
360
tests/auth_test.sh
Executable file
360
tests/auth_test.sh
Executable file
@@ -0,0 +1,360 @@
|
||||
#!/bin/bash
|
||||
|
||||
# auth_test.sh - Authentication System Test Suite
|
||||
# Tests the unified nostr_core_lib authentication system integrated into ginxsom
|
||||
|
||||
# Configuration
|
||||
SERVER_URL="http://localhost:9001"
|
||||
UPLOAD_ENDPOINT="${SERVER_URL}/upload"
|
||||
DB_PATH="db/ginxsom.db"
|
||||
TEST_DIR="tests/auth_test_tmp"
|
||||
|
||||
# Test keys for different scenarios
|
||||
TEST_USER1_PRIVKEY="5c0c523f52a5b6fad39ed2403092df8cebc36318b39383bca6c00808626fab3a"
|
||||
TEST_USER1_PUBKEY="79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
|
||||
|
||||
TEST_USER2_PRIVKEY="182c3a5e3b7a1b7e4f5c6b7c8b4a5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
|
||||
TEST_USER2_PUBKEY="c95195e5e7de1ad8c4d3c0ac4e8b5c0c4e0c4d3c1e5c8d4c2e7e9f4a5b6c7d8e"
|
||||
|
||||
echo "=== Ginxsom Authentication System Test Suite ==="
|
||||
echo "Testing unified nostr_core_lib authentication integration"
|
||||
echo "Timestamp: $(date -Iseconds)"
|
||||
echo
|
||||
|
||||
# Check prerequisites
|
||||
echo "[INFO] Checking prerequisites..."
|
||||
for cmd in nak curl jq sqlite3; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
echo "[ERROR] $cmd command not found"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if server is running
|
||||
if ! curl -s -f "${SERVER_URL}/" > /dev/null 2>&1; then
|
||||
echo "[ERROR] Server not running at $SERVER_URL"
|
||||
echo "[INFO] Start with: ./restart-all.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if database exists
|
||||
if [[ ! -f "$DB_PATH" ]]; then
|
||||
echo "[ERROR] Database not found at $DB_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[SUCCESS] All prerequisites met"
|
||||
echo
|
||||
|
||||
# Setup test environment and auth rules ONCE at the beginning
|
||||
echo "=== Setting up authentication rules ==="
|
||||
mkdir -p "$TEST_DIR"
|
||||
|
||||
# Enable authentication rules
|
||||
sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO auth_config (key, value) VALUES ('auth_rules_enabled', 'true');"
|
||||
|
||||
# Delete ALL existing auth rules and cache (clean slate)
|
||||
echo "Deleting all existing auth rules..."
|
||||
sqlite3 "$DB_PATH" "DELETE FROM auth_rules;"
|
||||
sqlite3 "$DB_PATH" "DELETE FROM auth_cache;"
|
||||
|
||||
# Set up all test rules at once
|
||||
echo "Creating test auth rules..."
|
||||
|
||||
# 1. Whitelist for TEST_USER1 for upload operations (priority 10)
|
||||
sqlite3 "$DB_PATH" "INSERT INTO auth_rules (rule_type, rule_target, operation, priority, enabled, description)
|
||||
VALUES ('pubkey_whitelist', '$TEST_USER1_PUBKEY', 'upload', 10, 1, 'TEST_WHITELIST_USER1');"
|
||||
|
||||
# 2. Blacklist for TEST_USER2 for upload operations (priority 5 - higher priority)
|
||||
sqlite3 "$DB_PATH" "INSERT INTO auth_rules (rule_type, rule_target, operation, priority, enabled, description)
|
||||
VALUES ('pubkey_blacklist', '$TEST_USER2_PUBKEY', 'upload', 5, 1, 'TEST_BLACKLIST_USER2');"
|
||||
|
||||
# 3. Hash blacklist (will be set after we create a test file)
|
||||
echo "test content for hash blacklist" > "$TEST_DIR/blacklisted_file.txt"
|
||||
BLACKLISTED_HASH=$(sha256sum "$TEST_DIR/blacklisted_file.txt" | cut -d' ' -f1)
|
||||
sqlite3 "$DB_PATH" "INSERT INTO auth_rules (rule_type, rule_target, operation, priority, enabled, description)
|
||||
VALUES ('hash_blacklist', '$BLACKLISTED_HASH', 'upload', 5, 1, 'TEST_HASH_BLACKLIST');"
|
||||
|
||||
echo "Hash blacklisted: $BLACKLISTED_HASH"
|
||||
|
||||
# Display the rules we created
|
||||
echo
|
||||
echo "Auth rules created:"
|
||||
sqlite3 "$DB_PATH" -header -column "SELECT rule_type, rule_target, operation, priority, enabled, description FROM auth_rules WHERE description LIKE 'TEST_%' ORDER BY priority;"
|
||||
echo
|
||||
|
||||
# Helper functions
|
||||
create_test_file() {
|
||||
local filename="$1"
|
||||
local content="${2:-test content for $filename}"
|
||||
local filepath="$TEST_DIR/$filename"
|
||||
echo "$content" > "$filepath"
|
||||
echo "$filepath"
|
||||
}
|
||||
|
||||
create_auth_event() {
|
||||
local privkey="$1"
|
||||
local operation="$2"
|
||||
local hash="$3"
|
||||
local expiration_offset="${4:-3600}" # 1 hour default
|
||||
|
||||
local expiration=$(date -d "+${expiration_offset} seconds" +%s)
|
||||
|
||||
local event_args=(-k 24242 -c "" --tag "t=$operation" --tag "expiration=$expiration" --sec "$privkey")
|
||||
|
||||
if [[ -n "$hash" ]]; then
|
||||
event_args+=(--tag "x=$hash")
|
||||
fi
|
||||
|
||||
nak event "${event_args[@]}"
|
||||
}
|
||||
|
||||
test_upload() {
|
||||
local test_name="$1"
|
||||
local privkey="$2"
|
||||
local file_path="$3"
|
||||
local expected_status="${4:-ANY}"
|
||||
|
||||
echo "=== $test_name ==="
|
||||
|
||||
local file_hash=$(sha256sum "$file_path" | cut -d' ' -f1)
|
||||
echo "File: $(basename "$file_path")"
|
||||
echo "Hash: $file_hash"
|
||||
echo "User pubkey: $(echo "$privkey" | nak key public)"
|
||||
|
||||
# Create auth event
|
||||
local event=$(create_auth_event "$privkey" "upload" "$file_hash")
|
||||
local auth_header="Nostr $(echo "$event" | base64 -w 0)"
|
||||
|
||||
# Make upload request
|
||||
local response_file=$(mktemp)
|
||||
local http_status=$(curl -s -w "%{http_code}" \
|
||||
-H "Authorization: $auth_header" \
|
||||
-H "Content-Type: text/plain" \
|
||||
--data-binary "@$file_path" \
|
||||
-X PUT "$UPLOAD_ENDPOINT" \
|
||||
-o "$response_file")
|
||||
|
||||
echo "HTTP Status: $http_status"
|
||||
echo "Server Response:"
|
||||
cat "$response_file" | jq . 2>/dev/null || cat "$response_file"
|
||||
echo
|
||||
|
||||
rm -f "$response_file"
|
||||
|
||||
if [[ "$expected_status" != "ANY" ]]; then
|
||||
if [[ "$http_status" == "$expected_status" ]]; then
|
||||
echo "✓ Expected HTTP $expected_status - PASSED"
|
||||
else
|
||||
echo "✗ Expected HTTP $expected_status, got $http_status - FAILED"
|
||||
fi
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
# Run the tests
|
||||
echo "=== Running Authentication Tests ==="
|
||||
echo
|
||||
|
||||
# Test 1: Whitelisted user (should succeed)
|
||||
test_file1=$(create_test_file "whitelisted_upload.txt" "Content from whitelisted user")
|
||||
test_upload "Test 1: Whitelisted User Upload" "$TEST_USER1_PRIVKEY" "$test_file1" "200"
|
||||
|
||||
# Test 2: Blacklisted user (should fail)
|
||||
test_file2=$(create_test_file "blacklisted_upload.txt" "Content from blacklisted user")
|
||||
test_upload "Test 2: Blacklisted User Upload" "$TEST_USER2_PRIVKEY" "$test_file2" "403"
|
||||
|
||||
# Test 3: Whitelisted user uploading blacklisted hash (blacklist should win due to higher priority)
|
||||
test_upload "Test 3: Whitelisted User + Blacklisted Hash" "$TEST_USER1_PRIVKEY" "$TEST_DIR/blacklisted_file.txt" "403"
|
||||
|
||||
# Test 4: Random user with no specific rules (should be allowed since no restrictive whitelist applies to all users)
|
||||
test_file4=$(create_test_file "random_upload.txt" "Content from random user")
|
||||
# Use a different private key that's not in any rules
|
||||
RANDOM_PRIVKEY="abcd1234567890abcd1234567890abcd1234567890abcd1234567890abcd1234"
|
||||
test_upload "Test 4: Random User (No Rules)" "$RANDOM_PRIVKEY" "$test_file4" "ANY"
|
||||
|
||||
# Test 5: Test with authentication disabled
|
||||
echo "=== Test 5: Authentication Disabled ==="
|
||||
echo "Disabling authentication rules..."
|
||||
sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO auth_config (key, value) VALUES ('auth_rules_enabled', 'false');"
|
||||
|
||||
test_file5=$(create_test_file "auth_disabled.txt" "Upload with auth disabled")
|
||||
test_upload "Test 5: Upload with Authentication Disabled" "$TEST_USER2_PRIVKEY" "$test_file5" "200"
|
||||
|
||||
# Re-enable authentication
|
||||
echo "Re-enabling authentication rules..."
|
||||
sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO auth_config (key, value) VALUES ('auth_rules_enabled', 'true');"
|
||||
echo
|
||||
|
||||
# Test failure modes - comprehensive edge case testing
|
||||
echo "=== Test 6: Invalid Authorization Header Formats ==="
|
||||
|
||||
# Helper function for failure mode tests
|
||||
test_failure_mode() {
|
||||
local test_name="$1"
|
||||
local auth_header="$2"
|
||||
local file_content="${3:-failure_test_content}"
|
||||
local expected_status="${4:-401}"
|
||||
|
||||
echo "=== $test_name ==="
|
||||
|
||||
local test_file=$(mktemp)
|
||||
echo "$file_content" > "$test_file"
|
||||
|
||||
local response_file=$(mktemp)
|
||||
local http_status=$(curl -s -w "%{http_code}" \
|
||||
${auth_header:+-H "Authorization: $auth_header"} \
|
||||
-H "Content-Type: text/plain" \
|
||||
--data-binary "@$test_file" \
|
||||
-X PUT "$UPLOAD_ENDPOINT" \
|
||||
-o "$response_file")
|
||||
|
||||
echo "HTTP Status: $http_status"
|
||||
echo "Server Response:"
|
||||
cat "$response_file" | jq . 2>/dev/null || cat "$response_file"
|
||||
echo
|
||||
|
||||
rm -f "$test_file" "$response_file"
|
||||
|
||||
if [[ "$http_status" == "$expected_status" ]]; then
|
||||
echo "✓ Expected HTTP $expected_status - PASSED"
|
||||
else
|
||||
echo "✗ Expected HTTP $expected_status, got $http_status - FAILED"
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
# Test 6a: Missing Authorization Header
|
||||
test_failure_mode "Test 6a: Missing Authorization Header" ""
|
||||
|
||||
# Test 6b: Invalid Authorization Prefix
|
||||
test_failure_mode "Test 6b: Invalid Authorization Prefix" "Bearer invalidtoken123"
|
||||
|
||||
# Test 6c: Invalid Base64 in Authorization
|
||||
test_failure_mode "Test 6c: Invalid Base64 in Authorization" "Nostr invalid!@#base64"
|
||||
|
||||
echo "=== Test 7: Malformed JSON Events ==="
|
||||
|
||||
# Test 7a: Invalid JSON Structure
|
||||
malformed_json='{"kind":24242,"content":"","created_at":' # Incomplete JSON
|
||||
malformed_b64=$(echo -n "$malformed_json" | base64 -w 0)
|
||||
test_failure_mode "Test 7a: Invalid JSON Structure" "Nostr $malformed_b64"
|
||||
|
||||
# Test 7b: Missing Required Fields
|
||||
missing_fields_json='{"kind":24242,"content":"","created_at":1234567890,"tags":[]}'
|
||||
missing_fields_b64=$(echo -n "$missing_fields_json" | base64 -w 0)
|
||||
test_failure_mode "Test 7b: Missing Required Fields (no pubkey)" "Nostr $missing_fields_b64"
|
||||
|
||||
echo "=== Test 8: Invalid Key Formats ==="
|
||||
|
||||
# Test 8a: Short Public Key
|
||||
echo "Test 8a: Short Public Key (32 chars instead of 64)"
|
||||
echo "short_key_test" > "$TEST_DIR/short_key.txt"
|
||||
file_hash=$(sha256sum "$TEST_DIR/short_key.txt" | cut -d' ' -f1)
|
||||
short_pubkey="1234567890abcdef1234567890abcdef" # 32 chars instead of 64
|
||||
short_key_event=$(cat << EOF
|
||||
{
|
||||
"kind": 24242,
|
||||
"content": "",
|
||||
"created_at": $(date +%s),
|
||||
"pubkey": "$short_pubkey",
|
||||
"tags": [["t", "upload"], ["x", "$file_hash"]],
|
||||
"id": "invalid_id",
|
||||
"sig": "invalid_signature"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
short_key_b64=$(echo -n "$short_key_event" | base64 -w 0)
|
||||
test_failure_mode "Test 8a: Short Public Key" "Nostr $short_key_b64"
|
||||
|
||||
# Test 8b: Non-hex Public Key
|
||||
echo "Test 8b: Non-hex Public Key"
|
||||
echo "nonhex_key_test" > "$TEST_DIR/nonhex_key.txt"
|
||||
file_hash=$(sha256sum "$TEST_DIR/nonhex_key.txt" | cut -d' ' -f1)
|
||||
nonhex_pubkey="gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg" # Invalid hex
|
||||
nonhex_key_event=$(cat << EOF
|
||||
{
|
||||
"kind": 24242,
|
||||
"content": "",
|
||||
"created_at": $(date +%s),
|
||||
"pubkey": "$nonhex_pubkey",
|
||||
"tags": [["t", "upload"], ["x", "$file_hash"]],
|
||||
"id": "invalid_id",
|
||||
"sig": "invalid_signature"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
nonhex_key_b64=$(echo -n "$nonhex_key_event" | base64 -w 0)
|
||||
test_failure_mode "Test 8b: Non-hex Public Key" "Nostr $nonhex_key_b64"
|
||||
|
||||
echo "=== Test 9: Wrong Event Kind ==="
|
||||
|
||||
# Test 9a: Wrong Kind (1 instead of 24242)
|
||||
echo "Test 9a: Wrong Kind (kind 1 instead of 24242)"
|
||||
echo "wrong_kind_test" > "$TEST_DIR/wrong_kind.txt"
|
||||
file_hash=$(sha256sum "$TEST_DIR/wrong_kind.txt" | cut -d' ' -f1)
|
||||
wrong_kind_event=$(nak event -k 1 -c "wrong kind test" --tag "t=upload" --tag "x=$file_hash" --sec "$TEST_USER1_PRIVKEY")
|
||||
wrong_kind_b64=$(echo -n "$wrong_kind_event" | base64 -w 0)
|
||||
test_failure_mode "Test 9a: Wrong Event Kind" "Nostr $wrong_kind_b64"
|
||||
|
||||
echo "=== Test 10: Missing or Invalid Tags ==="
|
||||
|
||||
# Test 10a: Missing 't' tag
|
||||
echo "Test 10a: Missing 't' (method) tag"
|
||||
echo "missing_t_tag_test" > "$TEST_DIR/missing_t_tag.txt"
|
||||
file_hash=$(sha256sum "$TEST_DIR/missing_t_tag.txt" | cut -d' ' -f1)
|
||||
missing_t_event=$(nak event -k 24242 -c "" --tag "x=$file_hash" --sec "$TEST_USER1_PRIVKEY")
|
||||
missing_t_b64=$(echo -n "$missing_t_event" | base64 -w 0)
|
||||
test_failure_mode "Test 10a: Missing 't' tag" "Nostr $missing_t_b64"
|
||||
|
||||
# Test 10b: Missing 'x' tag
|
||||
echo "Test 10b: Missing 'x' (hash) tag"
|
||||
echo "missing_x_tag_test" > "$TEST_DIR/missing_x_tag.txt"
|
||||
missing_x_event=$(nak event -k 24242 -c "" --tag "t=upload" --sec "$TEST_USER1_PRIVKEY")
|
||||
missing_x_b64=$(echo -n "$missing_x_event" | base64 -w 0)
|
||||
test_failure_mode "Test 10b: Missing 'x' tag" "Nostr $missing_x_b64"
|
||||
|
||||
# Test 10c: Hash mismatch in 'x' tag
|
||||
echo "Test 10c: Hash mismatch in 'x' tag"
|
||||
echo "hash_mismatch_test" > "$TEST_DIR/hash_mismatch.txt"
|
||||
wrong_hash="0000000000000000000000000000000000000000000000000000000000000000"
|
||||
hash_mismatch_event=$(nak event -k 24242 -c "" --tag "t=upload" --tag "x=$wrong_hash" --sec "$TEST_USER1_PRIVKEY")
|
||||
hash_mismatch_b64=$(echo -n "$hash_mismatch_event" | base64 -w 0)
|
||||
test_failure_mode "Test 10c: Hash mismatch" "Nostr $hash_mismatch_b64"
|
||||
|
||||
echo "=== Test 11: Expired Events ==="
|
||||
|
||||
# Test 11a: Event with past expiration
|
||||
echo "Test 11a: Event with past expiration"
|
||||
echo "expired_event_test" > "$TEST_DIR/expired_event.txt"
|
||||
file_hash=$(sha256sum "$TEST_DIR/expired_event.txt" | cut -d' ' -f1)
|
||||
past_time=$(($(date +%s) - 3600)) # 1 hour ago
|
||||
expired_event=$(nak event -k 24242 -c "" --tag "t=upload" --tag "x=$file_hash" --tag "expiration=$past_time" --sec "$TEST_USER1_PRIVKEY")
|
||||
expired_b64=$(echo -n "$expired_event" | base64 -w 0)
|
||||
test_failure_mode "Test 11a: Expired Event" "Nostr $expired_b64"
|
||||
|
||||
echo "=== Test 12: Invalid Signatures ==="
|
||||
|
||||
# Test 12a: Corrupted signature
|
||||
echo "Test 12a: Corrupted signature"
|
||||
echo "corrupted_sig_test" > "$TEST_DIR/corrupted_sig.txt"
|
||||
file_hash=$(sha256sum "$TEST_DIR/corrupted_sig.txt" | cut -d' ' -f1)
|
||||
valid_event=$(nak event -k 24242 -c "" --tag "t=upload" --tag "x=$file_hash" --sec "$TEST_USER1_PRIVKEY")
|
||||
# Corrupt the signature by changing the last character
|
||||
corrupted_event=$(echo "$valid_event" | sed 's/.\{1\}$/x/') # Replace last char with 'x'
|
||||
corrupted_b64=$(echo -n "$corrupted_event" | base64 -w 0)
|
||||
test_failure_mode "Test 12a: Corrupted Signature" "Nostr $corrupted_b64"
|
||||
|
||||
# Show final state
|
||||
echo "=== Final Database State ==="
|
||||
echo "Authentication rules left in database:"
|
||||
sqlite3 "$DB_PATH" -header -column "SELECT rule_type, rule_target, operation, priority, enabled, description FROM auth_rules WHERE description LIKE 'TEST_%' ORDER BY priority;"
|
||||
echo
|
||||
echo "Auth config:"
|
||||
sqlite3 "$DB_PATH" -header -column "SELECT key, value FROM auth_config WHERE key = 'auth_rules_enabled';"
|
||||
echo
|
||||
|
||||
echo "=== Test Suite Completed ==="
|
||||
echo "Comprehensive authentication and failure mode testing completed."
|
||||
echo "Auth rules have been left in the database for inspection."
|
||||
echo "To clean up, run: sqlite3 $DB_PATH \"DELETE FROM auth_rules WHERE description LIKE 'TEST_%';\""
|
||||
1
tests/auth_test_tmp/auth_disabled.txt
Normal file
1
tests/auth_test_tmp/auth_disabled.txt
Normal file
@@ -0,0 +1 @@
|
||||
Upload with auth disabled
|
||||
1
tests/auth_test_tmp/blacklisted_file.txt
Normal file
1
tests/auth_test_tmp/blacklisted_file.txt
Normal file
@@ -0,0 +1 @@
|
||||
test content for hash blacklist
|
||||
1
tests/auth_test_tmp/blacklisted_upload.txt
Normal file
1
tests/auth_test_tmp/blacklisted_upload.txt
Normal file
@@ -0,0 +1 @@
|
||||
Content from blacklisted user
|
||||
1
tests/auth_test_tmp/corrupted_sig.txt
Normal file
1
tests/auth_test_tmp/corrupted_sig.txt
Normal file
@@ -0,0 +1 @@
|
||||
corrupted_sig_test
|
||||
1
tests/auth_test_tmp/expired_event.txt
Normal file
1
tests/auth_test_tmp/expired_event.txt
Normal file
@@ -0,0 +1 @@
|
||||
expired_event_test
|
||||
1
tests/auth_test_tmp/hash_mismatch.txt
Normal file
1
tests/auth_test_tmp/hash_mismatch.txt
Normal file
@@ -0,0 +1 @@
|
||||
hash_mismatch_test
|
||||
1
tests/auth_test_tmp/missing_t_tag.txt
Normal file
1
tests/auth_test_tmp/missing_t_tag.txt
Normal file
@@ -0,0 +1 @@
|
||||
missing_t_tag_test
|
||||
1
tests/auth_test_tmp/missing_x_tag.txt
Normal file
1
tests/auth_test_tmp/missing_x_tag.txt
Normal file
@@ -0,0 +1 @@
|
||||
missing_x_tag_test
|
||||
1
tests/auth_test_tmp/nonhex_key.txt
Normal file
1
tests/auth_test_tmp/nonhex_key.txt
Normal file
@@ -0,0 +1 @@
|
||||
nonhex_key_test
|
||||
1
tests/auth_test_tmp/random_upload.txt
Normal file
1
tests/auth_test_tmp/random_upload.txt
Normal file
@@ -0,0 +1 @@
|
||||
Content from random user
|
||||
1
tests/auth_test_tmp/short_key.txt
Normal file
1
tests/auth_test_tmp/short_key.txt
Normal file
@@ -0,0 +1 @@
|
||||
short_key_test
|
||||
1
tests/auth_test_tmp/whitelisted_upload.txt
Normal file
1
tests/auth_test_tmp/whitelisted_upload.txt
Normal file
@@ -0,0 +1 @@
|
||||
Content from whitelisted user
|
||||
1
tests/auth_test_tmp/wrong_kind.txt
Normal file
1
tests/auth_test_tmp/wrong_kind.txt
Normal file
@@ -0,0 +1 @@
|
||||
wrong_kind_test
|
||||
33
tests/init_admin.sh
Executable file
33
tests/init_admin.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Admin Initialization Script for Ginxsom Testing
|
||||
# Sets up the test admin key in the database
|
||||
|
||||
set -e
|
||||
|
||||
# Test admin public key (must match TEST_ADMIN_PUBKEY from admin_test.sh)
|
||||
TEST_ADMIN_PUBKEY="2ef05348f28d24e0f0ed0751278442c27b62c823c37af8d8d89d8592c6ee84e7"
|
||||
|
||||
echo "Initializing admin access for testing..."
|
||||
|
||||
# Check if database exists
|
||||
if [ ! -f "db/ginxsom.db" ]; then
|
||||
echo "Error: Database db/ginxsom.db not found. Run ./db/init.sh first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configure admin settings
|
||||
sqlite3 db/ginxsom.db << EOF
|
||||
INSERT OR REPLACE INTO server_config (key, value, description) VALUES
|
||||
('admin_pubkey', '$TEST_ADMIN_PUBKEY', 'Nostr public key authorized for admin operations (test key)'),
|
||||
('admin_enabled', 'true', 'Enable admin interface');
|
||||
EOF
|
||||
|
||||
echo "Admin access configured successfully!"
|
||||
echo "Test admin public key: $TEST_ADMIN_PUBKEY"
|
||||
echo "Use private key from admin_test.sh to generate authentication tokens"
|
||||
|
||||
# Verify configuration
|
||||
echo ""
|
||||
echo "Current admin configuration:"
|
||||
sqlite3 db/ginxsom.db "SELECT key, value FROM server_config WHERE key IN ('admin_pubkey', 'admin_enabled');"
|
||||
49
tests/simple_auth_test.sh
Executable file
49
tests/simple_auth_test.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Simple authentication test
|
||||
set -e
|
||||
|
||||
SERVER_URL="http://localhost:9001"
|
||||
UPLOAD_ENDPOINT="${SERVER_URL}/upload"
|
||||
TEST_USER1_PRIVKEY="5c0c523f52a5b6fad39ed2403092df8cebc36318b39383bca6c00808626fab3a"
|
||||
|
||||
echo "=== Simple Authentication Test ==="
|
||||
|
||||
# Create a small test file
|
||||
echo "Test file content $(date)" > /tmp/simple_test.txt
|
||||
FILE_HASH=$(sha256sum /tmp/simple_test.txt | cut -d' ' -f1)
|
||||
|
||||
echo "Test file hash: $FILE_HASH"
|
||||
|
||||
# Create auth event
|
||||
EVENT=$(nak event -k 24242 -c "" \
|
||||
--tag "t=upload" \
|
||||
--tag "x=${FILE_HASH}" \
|
||||
--tag "expiration=$(date -d '+1 hour' +%s)" \
|
||||
--sec "$TEST_USER1_PRIVKEY")
|
||||
|
||||
echo "Generated event: $EVENT"
|
||||
|
||||
# Create auth header
|
||||
AUTH_HEADER="Nostr $(echo "$EVENT" | base64 -w 0)"
|
||||
|
||||
echo "Auth header length: ${#AUTH_HEADER}"
|
||||
|
||||
# Test upload
|
||||
echo "Testing upload..."
|
||||
HTTP_STATUS=$(curl -s -w "%{http_code}" \
|
||||
-H "Authorization: $AUTH_HEADER" \
|
||||
-H "Content-Type: text/plain" \
|
||||
--data-binary "@/tmp/simple_test.txt" \
|
||||
-X PUT "$UPLOAD_ENDPOINT" \
|
||||
-o /tmp/upload_response.txt)
|
||||
|
||||
echo "HTTP Status: $HTTP_STATUS"
|
||||
echo "Response:"
|
||||
cat /tmp/upload_response.txt
|
||||
echo
|
||||
|
||||
# Cleanup
|
||||
rm -f /tmp/simple_test.txt /tmp/upload_response.txt
|
||||
|
||||
echo "Test completed with status: $HTTP_STATUS"
|
||||
62
tests/simple_comprehensive_test.sh
Executable file
62
tests/simple_comprehensive_test.sh
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Simple comprehensive auth test
|
||||
SERVER_URL="http://localhost:9001"
|
||||
UPLOAD_ENDPOINT="${SERVER_URL}/upload"
|
||||
DB_PATH="../db/ginxsom.db"
|
||||
|
||||
# Test keys
|
||||
TEST_USER1_PRIVKEY="5c0c523f52a5b6fad39ed2403092df8cebc36318b39383bca6c00808626fab3a"
|
||||
TEST_USER1_PUBKEY="79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
|
||||
|
||||
echo "=== Simple Authentication Test ==="
|
||||
|
||||
# Test 1: Basic upload
|
||||
echo "Test 1: Basic upload"
|
||||
echo "test content" > test1.txt
|
||||
file_hash=$(sha256sum test1.txt | cut -d" " -f1)
|
||||
|
||||
# Create auth event
|
||||
event=$(nak event -k 24242 -c "" --tag "t=upload" --tag "expiration=$(date -d "+1 hour" +%s)" --tag "x=$file_hash" --sec "$TEST_USER1_PRIVKEY")
|
||||
auth_header="Nostr $(echo "$event" | base64 -w 0)"
|
||||
|
||||
# Make upload request
|
||||
response=$(curl -s -w "%{http_code}" -H "Authorization: $auth_header" -H "Content-Type: text/plain" --data-binary "@test1.txt" -X PUT "$UPLOAD_ENDPOINT" -o response1.json)
|
||||
|
||||
if [ "$response" = "200" ]; then
|
||||
echo "✓ Basic upload test PASSED (HTTP $response)"
|
||||
else
|
||||
echo "✗ Basic upload test FAILED (HTTP $response)"
|
||||
cat response1.json
|
||||
fi
|
||||
|
||||
# Test 2: Whitelist rule
|
||||
echo
|
||||
echo "Test 2: Pubkey whitelist"
|
||||
|
||||
# Clear rules and add whitelist
|
||||
sqlite3 "$DB_PATH" "DELETE FROM auth_rules WHERE description LIKE %TEST_%;"
|
||||
sqlite3 "$DB_PATH" "DELETE FROM auth_cache;"
|
||||
sqlite3 "$DB_PATH" "INSERT INTO auth_rules (rule_type, rule_target, operation, priority, enabled, description) VALUES (pubkey_whitelist, , upload, 10, 1, TEST_WHITELIST);"
|
||||
|
||||
echo "test content 2" > test2.txt
|
||||
file_hash2=$(sha256sum test2.txt | cut -d" " -f1)
|
||||
|
||||
event2=$(nak event -k 24242 -c "" --tag "t=upload" --tag "expiration=$(date -d "+1 hour" +%s)" --tag "x=$file_hash2" --sec "$TEST_USER1_PRIVKEY")
|
||||
auth_header2="Nostr $(echo "$event2" | base64 -w 0)"
|
||||
|
||||
response2=$(curl -s -w "%{http_code}" -H "Authorization: $auth_header2" -H "Content-Type: text/plain" --data-binary "@test2.txt" -X PUT "$UPLOAD_ENDPOINT" -o response2.json)
|
||||
|
||||
if [ "$response2" = "200" ]; then
|
||||
echo "✓ Whitelist test PASSED (HTTP $response2)"
|
||||
else
|
||||
echo "✗ Whitelist test FAILED (HTTP $response2)"
|
||||
cat response2.json
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
rm -f test1.txt test2.txt response1.json response2.json
|
||||
sqlite3 "$DB_PATH" "DELETE FROM auth_rules WHERE description LIKE %TEST_%;"
|
||||
sqlite3 "$DB_PATH" "DELETE FROM auth_cache;"
|
||||
|
||||
echo "=== Tests completed ==="
|
||||
1
tests/tests/auth_test_tmp/auth_disabled.txt
Normal file
1
tests/tests/auth_test_tmp/auth_disabled.txt
Normal file
@@ -0,0 +1 @@
|
||||
Upload with auth disabled
|
||||
1
tests/tests/auth_test_tmp/blacklisted_file.txt
Normal file
1
tests/tests/auth_test_tmp/blacklisted_file.txt
Normal file
@@ -0,0 +1 @@
|
||||
test content for hash blacklist
|
||||
1
tests/tests/auth_test_tmp/blacklisted_upload.txt
Normal file
1
tests/tests/auth_test_tmp/blacklisted_upload.txt
Normal file
@@ -0,0 +1 @@
|
||||
Content from blacklisted user
|
||||
1
tests/tests/auth_test_tmp/corrupted_sig.txt
Normal file
1
tests/tests/auth_test_tmp/corrupted_sig.txt
Normal file
@@ -0,0 +1 @@
|
||||
corrupted_sig_test
|
||||
1
tests/tests/auth_test_tmp/expired_event.txt
Normal file
1
tests/tests/auth_test_tmp/expired_event.txt
Normal file
@@ -0,0 +1 @@
|
||||
expired_event_test
|
||||
1
tests/tests/auth_test_tmp/hash_mismatch.txt
Normal file
1
tests/tests/auth_test_tmp/hash_mismatch.txt
Normal file
@@ -0,0 +1 @@
|
||||
hash_mismatch_test
|
||||
1
tests/tests/auth_test_tmp/missing_t_tag.txt
Normal file
1
tests/tests/auth_test_tmp/missing_t_tag.txt
Normal file
@@ -0,0 +1 @@
|
||||
missing_t_tag_test
|
||||
1
tests/tests/auth_test_tmp/missing_x_tag.txt
Normal file
1
tests/tests/auth_test_tmp/missing_x_tag.txt
Normal file
@@ -0,0 +1 @@
|
||||
missing_x_tag_test
|
||||
1
tests/tests/auth_test_tmp/nonhex_key.txt
Normal file
1
tests/tests/auth_test_tmp/nonhex_key.txt
Normal file
@@ -0,0 +1 @@
|
||||
nonhex_key_test
|
||||
1
tests/tests/auth_test_tmp/random_upload.txt
Normal file
1
tests/tests/auth_test_tmp/random_upload.txt
Normal file
@@ -0,0 +1 @@
|
||||
Content from random user
|
||||
1
tests/tests/auth_test_tmp/short_key.txt
Normal file
1
tests/tests/auth_test_tmp/short_key.txt
Normal file
@@ -0,0 +1 @@
|
||||
short_key_test
|
||||
1
tests/tests/auth_test_tmp/whitelisted_upload.txt
Normal file
1
tests/tests/auth_test_tmp/whitelisted_upload.txt
Normal file
@@ -0,0 +1 @@
|
||||
Content from whitelisted user
|
||||
1
tests/tests/auth_test_tmp/wrong_kind.txt
Normal file
1
tests/tests/auth_test_tmp/wrong_kind.txt
Normal file
@@ -0,0 +1 @@
|
||||
wrong_kind_test
|
||||
Reference in New Issue
Block a user