#!/usr/bin/env bash # Checks the Mastodon client API the way a client first meets it. # usage: tools/smoke/mastodon-api.sh https://privapub.thepra.dev [ACCESS_TOKEN] set -euo pipefail BASE="${1:?base url}"; TOKEN="${2:-}" fail() { echo "::error::$*"; exit 1; } json() { python3 -c "import sys,json; d=json.load(sys.stdin); $1"; } # the version clients branch on (Mastodon invariant 6): Mastodon 4.5's, then PrivaPub's release version=$(curl -fsS "$BASE/api/v1/instance" | json "print(d['version'])") || fail "instance v1" case "$version" in "4.5.0 (compatible; PrivaPub"*) ;; *) fail "instance v1 says version '$version', not 4.5.0 (compatible; PrivaPub ...)" ;; esac v2=$(curl -fsS "$BASE/api/v2/instance") || fail "instance v2" echo "$v2" | json "assert d['configuration']['statuses']['max_characters'] > 0" || fail "instance v2" echo "$v2" | json "assert d['version'] == '$version' and d['api_versions']['mastodon'] == 7" || fail "instance v2's version or api_versions" vapid=$(echo "$v2" | json "import base64; k = d['configuration']['vapid']['public_key']; assert len(base64.urlsafe_b64decode(k)) == 65; print(k)") \ || fail "instance v2 gives no VAPID key (configuration.vapid.public_key)" curl -fsS "$BASE/.well-known/oauth-authorization-server" | json "assert d['token_endpoint'].endswith('/oauth/token')" || fail "oauth discovery" app=$(curl -fsS -X POST "$BASE/api/v1/apps" -d 'client_name=privapub-smoke&redirect_uris=urn:ietf:wg:oauth:2.0:oob&scopes=read') || fail "app registration" id=$(echo "$app" | json "print(d['client_id'])"); secret=$(echo "$app" | json "print(d['client_secret'])") [ "$(echo "$app" | json "print(d['vapid_key'])")" = "$vapid" ] || fail "the app's vapid_key is not the instance's VAPID key" app_token=$(curl -fsS -X POST "$BASE/oauth/token" -d "grant_type=client_credentials&client_id=$id&client_secret=$secret&scope=read" | json "print(d['access_token'])") || fail "client credentials" curl -fsS -H "Authorization: Bearer $app_token" "$BASE/api/v1/apps/verify_credentials" | json "assert d['name'] == 'privapub-smoke'" || fail "app verify_credentials" code=$(curl -s -o /dev/null -w '%{http_code}' -H "Authorization: Bearer $app_token" "$BASE/api/v1/accounts/verify_credentials") [ "$code" = "401" ] || fail "an app token reached a user endpoint ($code)" curl -fsS "$BASE/api/v1/timelines/public?limit=2" | json "assert isinstance(d, list)" || fail "public timeline" curl -fsS -X POST "$BASE/oauth/revoke" -d "token=$app_token&client_id=$id&client_secret=$secret" -o /dev/null || fail "revoke" if [ -n "$TOKEN" ]; then curl -fsS -H "Authorization: Bearer $TOKEN" "$BASE/api/v1/accounts/verify_credentials" | json "assert d['source'] is not None" || fail "verify_credentials" curl -fsS -H "Authorization: Bearer $TOKEN" "$BASE/api/v1/timelines/home?limit=5" | json "assert isinstance(d, list)" || fail "home" curl -fsS -H "Authorization: Bearer $TOKEN" "$BASE/api/v1/notifications?limit=5" | json "assert isinstance(d, list)" || fail "notifications" fi echo "mastodon api ok: $version"