feat: Add Nostr identity and trust tier tests (#44)
Some checks failed
CI / Typecheck & Lint (pull_request) Failing after 1s
Some checks failed
CI / Typecheck & Lint (pull_request) Failing after 1s
This commit is contained in:
21
scripts/gen_nostr_event.js
Normal file
21
scripts/gen_nostr_event.js
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
const { generatePrivateKey, getPublicKey, finalizeEvent } = require('nostr-tools');
|
||||
|
||||
const privateKey = generatePrivateKey();
|
||||
const publicKey = getPublicKey(privateKey);
|
||||
|
||||
const nonce = process.argv[2]; // Nonce from challenge endpoint
|
||||
|
||||
if (!nonce) {
|
||||
console.error("Usage: node gen_nostr_event.js <nonce>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const event = finalizeEvent({
|
||||
kind: 27235,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [['challenge', nonce]],
|
||||
content: "NIP-27235 challenge response",
|
||||
}, privateKey);
|
||||
|
||||
console.log(JSON.stringify(event));
|
||||
150
timmy_test.sh
150
timmy_test.sh
@@ -422,6 +422,156 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tests 17-23 — Nostr Identity & Trust Tiers
|
||||
# ---------------------------------------------------------------------------
|
||||
sep "Tests 17-23 — Nostr Identity & Trust Tiers"
|
||||
|
||||
# Initialize Nostr keys and other variables
|
||||
NOSTR_PRIV_KEY=$(node -e "const { generatePrivateKey } = require('nostr-tools'); console.log(generatePrivateKey());")
|
||||
NOSTR_PUB_KEY=$(node -e "const { getPublicKey } = require('nostr-tools'); console.log(getPublicKey('$NOSTR_PRIV_KEY'));")
|
||||
CHALLENGE_NONCE=""
|
||||
NOSTR_TOKEN=""
|
||||
IDENTITY_PUBKEY=""
|
||||
|
||||
# Test 17 — POST /api/identity/challenge
|
||||
sep "Test 17 — POST /api/identity/challenge"
|
||||
T17_RES=$(curl -s -w "\n%{http_code}" -X POST "$BASE/api/identity/challenge")
|
||||
T17_BODY=$(echo "$T17_RES" | sed '$d')
|
||||
T17_CODE=$(echo "$T17_RES" | tail -n1)
|
||||
CHALLENGE_NONCE=$(jq_field "$T17_BODY" '.nonce')
|
||||
EXPIRES_AT=$(jq_field "$T17_BODY" '.expiresAt')
|
||||
|
||||
if [[ "$T17_CODE" == "200" && -n "$CHALLENGE_NONCE" && ${#CHALLENGE_NONCE} == 32 && -n "$EXPIRES_AT" ]]; then
|
||||
note PASS "HTTP 200, nonce and expiresAt returned"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
note FAIL "code=$T17_CODE body=$T17_BODY"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
|
||||
# Test 18 — POST /api/identity/verify with valid signed NIP-27235 event
|
||||
sep "Test 18 — POST /api/identity/verify (valid)"
|
||||
if [[ -n "$CHALLENGE_NONCE" ]]; then
|
||||
VALID_EVENT_JSON=$(node scripts/gen_nostr_event.js "$CHALLENGE_NONCE")
|
||||
T18_RES=$(curl -s -w "\n%{http_code}" -X POST "$BASE/api/identity/verify" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$VALID_EVENT_JSON")
|
||||
T18_BODY=$(echo "$T18_RES" | sed '$d')
|
||||
T18_CODE=$(echo "$T18_RES" | tail -n1)
|
||||
NOSTR_TOKEN=$(jq_field "$T18_BODY" '.nostr_token')
|
||||
IDENTITY_PUBKEY=$(jq_field "$T18_BODY" '.pubkey')
|
||||
TRUST_TIER=$(jq_field "$T18_BODY" '.trust')
|
||||
|
||||
if [[ "$T18_CODE" == "200" && -n "$NOSTR_TOKEN" && "$IDENTITY_PUBKEY" == "$NOSTR_PUB_KEY" && -n "$TRUST_TIER" ]]; then
|
||||
note PASS "HTTP 200, nostr_token, pubkey, trust returned"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
note FAIL "code=$T18_CODE body=$T18_BODY"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
else
|
||||
note SKIP "No challenge nonce from T17 — skipping Test 18"
|
||||
SKIP=$((SKIP+1))
|
||||
fi
|
||||
|
||||
# Test 19 — GET /api/estimate with X-Nostr-Token header for a new identity
|
||||
sep "Test 19 — GET /api/estimate (free tier)"
|
||||
if [[ -n "$NOSTR_TOKEN" ]]; then
|
||||
T19_RES=$(curl -s -w "\n%{http_code}" "$BASE/api/estimate" -H "X-Nostr-Token: $NOSTR_TOKEN")
|
||||
T19_BODY=$(echo "$T19_RES" | sed '$d')
|
||||
T19_CODE=$(echo "$T19_RES" | tail -n1)
|
||||
FREE_TIER_SERVE=$(jq_field "$T19_BODY" '.free_tier.serve')
|
||||
|
||||
if [[ "$T19_CODE" == "200" && "$FREE_TIER_SERVE" == "free" ]]; then
|
||||
note PASS "HTTP 200, free_tier.serve is 'free'"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
note FAIL "code=$T19_CODE body=$T19_BODY"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
else
|
||||
note SKIP "No nostr_token from T18 — skipping Test 19"
|
||||
SKIP=$((SKIP+1))
|
||||
fi
|
||||
|
||||
# Test 20 — POST /api/identity/verify with invalid signature
|
||||
sep "Test 20 — POST /api/identity/verify (invalid signature)"
|
||||
if [[ -n "$CHALLENGE_NONCE" ]]; then
|
||||
INVALID_PRIV_KEY=$(node -e "const { generatePrivateKey } = require('nostr-tools'); console.log(generatePrivateKey());")
|
||||
# Generate a valid event but with a different (invalid) private key
|
||||
INVALID_EVENT_JSON=$(node -e "const { getPublicKey, finalizeEvent } = require('nostr-tools'); const privateKey = '$INVALID_PRIV_KEY'; const event = finalizeEvent({ kind: 27235, created_at: Math.floor(Date.now() / 1000), tags: [['challenge', '$CHALLENGE_NONCE']], content: 'NIP-27235 challenge response' }, privateKey); console.log(JSON.stringify(event));")
|
||||
|
||||
T20_RES=$(curl -s -w "\n%{http_code}" -X POST "$BASE/api/identity/verify" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$INVALID_EVENT_JSON")
|
||||
T20_CODE=$(echo "$T20_RES" | tail -n1)
|
||||
|
||||
if [[ "$T20_CODE" == "401" ]]; then
|
||||
note PASS "HTTP 401 for invalid signature"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
note FAIL "code=$T20_CODE"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
else
|
||||
note SKIP "No challenge nonce from T17 — skipping Test 20"
|
||||
SKIP=$((SKIP+1))
|
||||
fi
|
||||
|
||||
# Test 21 — POST /api/identity/verify with expired nonce
|
||||
sep "Test 21 — POST /api/identity/verify (expired nonce)"
|
||||
# We'll generate a new challenge for this test, then wait for it to expire.
|
||||
# Assuming a short expiration for testing purposes (e.g., 5 seconds).
|
||||
# In a real scenario, this might be longer or handled with mocked time.
|
||||
|
||||
T21_CHALLENGE_RES=$(curl -s -w "\n%{http_code}" -X POST "$BASE/api/identity/challenge")
|
||||
T21_CHALLENGE_BODY=$(echo "$T21_CHALLENGE_RES" | sed '$d')
|
||||
T21_CHALLENGE_CODE=$(echo "$T21_CHALLENGE_RES" | tail -n1)
|
||||
T21_NONCE=$(jq_field "$T21_CHALLENGE_BODY" '.nonce')
|
||||
|
||||
if [[ "$T21_CHALLENGE_CODE" == "200" && -n "$T21_NONCE" ]]; then
|
||||
note "Waiting 6 seconds for nonce to expire..."
|
||||
sleep 6 # Wait for the nonce to expire (assuming expiry < 6 seconds)
|
||||
|
||||
EXPIRED_EVENT_JSON=$(node scripts/gen_nostr_event.js "$T21_NONCE")
|
||||
T21_RES=$(curl -s -w "\n%{http_code}" -X POST "$BASE/api/identity/verify" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$EXPIRED_EVENT_JSON")
|
||||
T21_CODE=$(echo "$T21_RES" | tail -n1)
|
||||
|
||||
if [[ "$T21_CODE" == "401" ]]; then
|
||||
note PASS "HTTP 401 for expired nonce"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
note FAIL "code=$T21_CODE"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
else
|
||||
note SKIP "Failed to get challenge nonce for T21 — skipping Test 21"
|
||||
SKIP=$((SKIP+1))
|
||||
fi
|
||||
|
||||
# Test 22 — GET /api/estimate without X-Nostr-Token header
|
||||
sep "Test 22 — GET /api/estimate (no token)"
|
||||
T22_RES=$(curl -s -w "\n%{http_code}" "$BASE/api/estimate")
|
||||
T22_BODY=$(echo "$T22_RES" | sed '$d')
|
||||
T22_CODE=$(echo "$T22_RES" | tail -n1)
|
||||
FREE_TIER_SERVE_NO_TOKEN=$(jq_field "$T22_BODY" '.free_tier.serve')
|
||||
|
||||
if [[ "$T22_CODE" == "200" && ("$FREE_TIER_SERVE_NO_TOKEN" == "pay" || -z "$FREE_TIER_SERVE_NO_TOKEN") ]]; then
|
||||
note PASS "HTTP 200, free_tier.serve is 'pay' or absent without token"
|
||||
PASS=$((PASS+1))
|
||||
else
|
||||
note FAIL "code=$T22_CODE body=$T22_BODY"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
|
||||
# Test 23 — GET /api/estimate with X-Nostr-Token for a trust-exhausted identity
|
||||
sep "Test 23 — GET /api/estimate (trust exhausted)"
|
||||
note SKIP "Test 23 — requires exhausting trust tier (complex setup); skipping for now"
|
||||
SKIP=$((SKIP+1))
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Summary
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user