v0.1.10 - In the middle of working on getting admin api working
This commit is contained in:
236
Trash/admin_test.sh
Executable file
236
Trash/admin_test.sh
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/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 endpoint="$2"
|
||||
local content="admin_request"
|
||||
local expiration=$(($(date +%s) + 3600)) # 1 hour from now
|
||||
|
||||
# Create Nostr event with nak - use kind 33335 for admin/configuration events
|
||||
local event=$(nak event -k 33335 -c "$content" \
|
||||
--tag method="$method" \
|
||||
--tag endpoint="$endpoint" \
|
||||
--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 with method and endpoint
|
||||
local event=$(create_admin_event "$method" "$endpoint")
|
||||
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
|
||||
91
Trash/schema.sql
Normal file
91
Trash/schema.sql
Normal file
@@ -0,0 +1,91 @@
|
||||
-- Ginxsom Blossom Server Database Schema
|
||||
-- SQLite database for blob metadata and server configuration
|
||||
|
||||
-- Enable foreign key constraints
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
-- Main blobs table for storing blob metadata
|
||||
CREATE TABLE IF NOT EXISTS blobs (
|
||||
sha256 TEXT PRIMARY KEY NOT NULL, -- SHA-256 hash (64 hex chars)
|
||||
size INTEGER NOT NULL, -- File size in bytes
|
||||
type TEXT NOT NULL, -- MIME type
|
||||
uploaded_at INTEGER NOT NULL, -- Unix timestamp
|
||||
uploader_pubkey TEXT, -- Nostr public key (optional)
|
||||
filename TEXT, -- Original filename (optional)
|
||||
CHECK (length(sha256) = 64), -- Ensure valid SHA-256 hash length
|
||||
CHECK (size >= 0), -- Ensure non-negative size
|
||||
CHECK (uploaded_at > 0) -- Ensure valid timestamp
|
||||
);
|
||||
|
||||
-- Unified configuration table (replaces server_config and auth_config)
|
||||
CREATE TABLE IF NOT EXISTS config (
|
||||
key TEXT PRIMARY KEY NOT NULL, -- Configuration key
|
||||
value TEXT NOT NULL, -- Configuration value
|
||||
description TEXT, -- Human-readable description
|
||||
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')), -- Creation timestamp
|
||||
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')) -- Last update timestamp
|
||||
);
|
||||
|
||||
-- Indexes for performance optimization
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_uploaded_at ON blobs(uploaded_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_uploader_pubkey ON blobs(uploader_pubkey);
|
||||
CREATE INDEX IF NOT EXISTS idx_blobs_type ON blobs(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_config_updated_at ON config(updated_at);
|
||||
|
||||
-- Insert default unified configuration
|
||||
INSERT OR IGNORE INTO config (key, value, description) VALUES
|
||||
('max_file_size', '104857600', 'Maximum file size in bytes (100MB)'),
|
||||
('auth_rules_enabled', 'false', 'Whether authentication rules are enabled for uploads'),
|
||||
('server_name', 'ginxsom', 'Server name for responses'),
|
||||
('admin_pubkey', '', 'Admin public key for API access'),
|
||||
('admin_enabled', 'true', 'Whether admin API is enabled'),
|
||||
('nip42_require_auth', 'false', 'Enable NIP-42 challenge/response authentication'),
|
||||
('nip42_challenge_timeout', '600', 'NIP-42 challenge timeout in seconds'),
|
||||
('nip42_time_tolerance', '300', 'NIP-42 timestamp tolerance in seconds');
|
||||
|
||||
-- Authentication rules table for whitelist/blacklist functionality
|
||||
CREATE TABLE IF NOT EXISTS auth_rules (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
rule_type TEXT NOT NULL, -- 'pubkey_blacklist', 'pubkey_whitelist',
|
||||
-- 'hash_blacklist', 'mime_blacklist', 'mime_whitelist'
|
||||
rule_target TEXT NOT NULL, -- The pubkey, hash, or MIME type to match
|
||||
operation TEXT NOT NULL DEFAULT '*', -- 'upload', 'delete', 'list', or '*' for all
|
||||
enabled INTEGER NOT NULL DEFAULT 1, -- 1 = enabled, 0 = disabled
|
||||
priority INTEGER NOT NULL DEFAULT 100,-- Lower number = higher priority
|
||||
description TEXT, -- Human-readable description
|
||||
created_by TEXT, -- Admin pubkey who created the rule
|
||||
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
|
||||
-- Constraints
|
||||
CHECK (rule_type IN ('pubkey_blacklist', 'pubkey_whitelist',
|
||||
'hash_blacklist', 'mime_blacklist', 'mime_whitelist')),
|
||||
CHECK (operation IN ('upload', 'delete', 'list', '*')),
|
||||
CHECK (enabled IN (0, 1)),
|
||||
CHECK (priority >= 0),
|
||||
|
||||
-- Unique constraint: one rule per type/target/operation combination
|
||||
UNIQUE(rule_type, rule_target, operation)
|
||||
);
|
||||
|
||||
|
||||
-- Indexes for performance optimization
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_type_target ON auth_rules(rule_type, rule_target);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_operation ON auth_rules(operation);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_enabled ON auth_rules(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_priority ON auth_rules(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_auth_rules_type_operation ON auth_rules(rule_type, operation, enabled);
|
||||
|
||||
|
||||
-- View for storage statistics
|
||||
CREATE VIEW IF NOT EXISTS storage_stats AS
|
||||
SELECT
|
||||
COUNT(*) as total_blobs,
|
||||
SUM(size) as total_bytes,
|
||||
AVG(size) as avg_blob_size,
|
||||
MIN(uploaded_at) as first_upload,
|
||||
MAX(uploaded_at) as last_upload,
|
||||
COUNT(DISTINCT uploader_pubkey) as unique_uploaders
|
||||
FROM blobs;
|
||||
|
||||
|
||||
80
Trash/test_admin_api.sh
Executable file
80
Trash/test_admin_api.sh
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for Admin API functionality
|
||||
# Demonstrates the new unified config system with automatic cache refresh
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== Admin API Configuration Test ==="
|
||||
echo
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Test the GET config API
|
||||
echo -e "${BLUE}1. Getting current configuration:${NC}"
|
||||
curl -s "http://localhost:9001/api/config" | jq '.' || echo "jq not available, showing raw output:"
|
||||
curl -s "http://localhost:9001/api/config"
|
||||
echo
|
||||
echo
|
||||
|
||||
# Test setting auth_rules_enabled to false
|
||||
echo -e "${BLUE}2. Disabling authentication (auth_rules_enabled=false):${NC}"
|
||||
response=$(curl -s -X PUT \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"value": "false"}' \
|
||||
"http://localhost:9001/api/config/auth_rules_enabled")
|
||||
echo "$response"
|
||||
echo
|
||||
|
||||
# Verify database was updated
|
||||
echo -e "${BLUE}3. Verifying database update:${NC}"
|
||||
sqlite3 db/ginxsom.db "SELECT key, value, updated_at FROM config WHERE key = 'auth_rules_enabled'"
|
||||
echo
|
||||
|
||||
# Test that cache refresh worked by attempting upload without auth
|
||||
echo -e "${BLUE}4. Testing cache refresh - upload without authentication:${NC}"
|
||||
upload_result=$(echo "test content" | curl -s -X PUT -H "Content-Type: text/plain" -d @- http://localhost:9001/upload)
|
||||
echo "$upload_result"
|
||||
if echo "$upload_result" | grep -q "authorization_required"; then
|
||||
echo -e "${GREEN}✅ Cache refresh working - authentication correctly disabled${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Cache refresh may not be working${NC}"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test setting auth_rules_enabled back to true
|
||||
echo -e "${BLUE}5. Re-enabling authentication (auth_rules_enabled=true):${NC}"
|
||||
response=$(curl -s -X PUT \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"value": "true"}' \
|
||||
"http://localhost:9001/api/config/auth_rules_enabled")
|
||||
echo "$response"
|
||||
echo
|
||||
|
||||
# Test another config setting
|
||||
echo -e "${BLUE}6. Testing another config key (max_file_size):${NC}"
|
||||
response=$(curl -s -X PUT \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"value": "104857600"}' \
|
||||
"http://localhost:9001/api/config/max_file_size")
|
||||
echo "$response"
|
||||
echo
|
||||
|
||||
# Show final config state
|
||||
echo -e "${BLUE}7. Final configuration state:${NC}"
|
||||
echo "Database content:"
|
||||
sqlite3 db/ginxsom.db "SELECT key, value, updated_at FROM config ORDER BY updated_at DESC LIMIT 5"
|
||||
echo
|
||||
|
||||
echo -e "${GREEN}=== Admin API Test Complete ===${NC}"
|
||||
echo "The admin API is working with:"
|
||||
echo "- ✅ Unified config table (no more dual server_config/auth_config)"
|
||||
echo "- ✅ Individual key endpoints (PUT /api/config/<key>)"
|
||||
echo "- ✅ JSON request body parsing ({\"value\": \"...\"})"
|
||||
echo "- ✅ Automatic cache refresh after updates"
|
||||
echo "- ✅ Environment variable cache control support"
|
||||
echo "- ⏳ Admin authentication (temporarily disabled for testing)"
|
||||
Reference in New Issue
Block a user