PrivaPub dropped Move as an unknown type and showed no `moved` on accounts. Now a Move is believed as Mastodon believes it: the moving account sends it about itself, and the new account, read again from its own server, names it in alsoKnownAs (now kept on remote accounts). The old account then shows the new one as `moved` in the Mastodon API. The personas following it keep following it: following the new account on their behalf would tell another server about them, so that waits for the owner. Checked live against GoToSocial (scenarios/moves.sh: an alias, a move, 6 checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
49 lines
4.1 KiB
Bash
49 lines
4.1 KiB
Bash
# Account moves into PrivaPub's view: an account alice follows on GoToSocial moves to a new account there. The new one
|
|
# names the old among its aliases (/api/v1/accounts/alias), the old moves (/api/v1/accounts/move), GoToSocial sends its
|
|
# Move to the old one's followers, and PrivaPub shows the old account moved to the new (`moved`). Needs the gts peer.
|
|
G=https://gts.test:6443
|
|
gcurl() { curl -k --resolve gts.test:6443:127.0.0.1 "$@"; }
|
|
MOVE_PASSWORD='Gts-Pasture-Pass-1!'
|
|
# gts_account <name>: a confirmed GoToSocial account and its token
|
|
gts_account() {
|
|
podman exec pasture-gts /gotosocial/gotosocial admin account create --username "$1" --email "$1@gts.test" --password "$MOVE_PASSWORD" >/dev/null 2>&1
|
|
podman exec pasture-gts /gotosocial/gotosocial admin account confirm --username "$1" >/dev/null 2>&1
|
|
local app id secret code jar
|
|
jar=$(mktemp); app=$(gcurl -s -X POST $G/api/v1/apps -d 'client_name=pasture&redirect_uris=urn:ietf:wg:oauth:2.0:oob&scopes=read+write+follow')
|
|
id=$(echo "$app" | j "print(d['client_id'])"); secret=$(echo "$app" | j "print(d['client_secret'])")
|
|
gcurl -s -o /dev/null -c "$jar" -b "$jar" "$G/oauth/authorize?client_id=$id&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=read+write+follow"
|
|
gcurl -s -o /dev/null -c "$jar" -b "$jar" -X POST $G/auth/sign_in --data-urlencode "username=$1@gts.test" --data-urlencode "password=$MOVE_PASSWORD"
|
|
code=$(gcurl -s -o /dev/null -w '%{redirect_url}' -c "$jar" -b "$jar" -X POST "$G/oauth/authorize" | sed -n 's/.*[?&]code=\([^&]*\).*/\1/p')
|
|
rm -f "$jar"
|
|
gcurl -s -X POST $G/oauth/token -d "grant_type=authorization_code&code=$code&client_id=$id&client_secret=$secret&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=read+write+follow" | j "print(d['access_token'])"
|
|
}
|
|
|
|
echo "moves"
|
|
PT=$(privapub_token alice)
|
|
PH="Authorization: Bearer $PT"
|
|
[ -n "$PT" ] && ok "PrivaPub token for alice" || { ko "PrivaPub token"; return 1; }
|
|
run=$(date +%s)
|
|
old="mvold$run"; new="mvnew$run"
|
|
OT=$(gts_account "$old"); NT=$(gts_account "$new")
|
|
[ -n "$OT" ] && [ -n "$NT" ] && ok "two GoToSocial accounts, the one that moves and the one it moves to" || { ko "GoToSocial accounts"; return 1; }
|
|
|
|
echo " following the old account"
|
|
old_on_p=$(curl -s -H "$PH" "$P/api/v2/search?q=$old@gts.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])")
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$old_on_p/follow"
|
|
# (GoToSocial makes its accounts locked: the old one approves alice)
|
|
until_true 30 '[ -n "$(gcurl -s -H "Authorization: Bearer $OT" "$G/api/v1/follow_requests" | j "print(d[0][\"id\"])")" ]'
|
|
gcurl -s -o /dev/null -X POST -H "Authorization: Bearer $OT" "$G/api/v1/follow_requests/$(gcurl -s -H "Authorization: Bearer $OT" "$G/api/v1/follow_requests" | j "print(d[0]['id'])")/authorize"
|
|
until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$old_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \
|
|
&& ok "alice follows the account that will move" || ko "alice's follow of the old account never took"
|
|
|
|
echo " the move"
|
|
gcurl -s -o /dev/null -X POST -H "Authorization: Bearer $NT" "$G/api/v1/accounts/alias" -H 'Content-Type: application/json' \
|
|
-d "{\"also_known_as_uris\":[\"https://gts.test/users/$old\"]}"
|
|
moved=$(gcurl -s -o /dev/null -w '%{http_code}' -X POST -H "Authorization: Bearer $OT" "$G/api/v1/accounts/move" -H 'Content-Type: application/json' \
|
|
-d "{\"password\":\"$MOVE_PASSWORD\",\"moved_to_uri\":\"https://gts.test/users/$new\"}")
|
|
[ "$moved" = "202" ] || [ "$moved" = "200" ] && ok "the old account moves on GoToSocial" || ko "GoToSocial refused the move ($moved)"
|
|
until_true 60 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/$old_on_p" | j "print((d.get(\"moved\") or {}).get(\"acct\"))")" = "$new@gts.test" ]' \
|
|
&& ok "PrivaPub shows the old account moved to the new one" || ko "PrivaPub does not show the move ($(curl -s -H "$PH" "$P/api/v1/accounts/$old_on_p" | j "print(d.get('moved'))"))"
|
|
[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$old_on_p" | j "print(d[0]['following'])")" = "True" ] \
|
|
&& ok "and alice still follows the old account: following the new one is hers to do" || ko "alice's follow of the old account changed"
|