2026-10-05 18:39:46 +02:00
# 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
2026-10-05 20:57:43 +02:00
# Move to the old one's followers, PrivaPub shows the old account moved to the new (`moved`) and moves alice's follow
# there. Needs the gts peer.
2026-10-05 18:39:46 +02:00
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'))" ) )"
2026-10-05 20:57:43 +02:00
# as Mastodon does it (owner decision 2026-10-05): alice's follow moves to the new account, which GoToSocial makes
# locked, so it arrives as a request the new account approves
new_on_p = $( curl -s -H " $PH " " $P /api/v1/accounts/ $old_on_p " | j "print((d.get('moved') or {}).get('id'))" )
until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$new_on_p" | j "print(d[0][\"following\"] or d[0][\"requested\"])")" = "True" ]' \
&& ok "PrivaPub moves alice's follow to the new account" || ko "alice does not follow the new account"
[ " $( curl -s -H " $PH " " $P /api/v1/accounts/relationships?id[]= $old_on_p " | j "print(d[0]['following'] or d[0]['requested'])" ) " = "False" ] \
&& ok "and no longer follows the old one" || ko "alice still follows the old account"
until_true 30 '[ -n "$(gcurl -s -H "Authorization: Bearer $NT" "$G/api/v1/follow_requests" | j "print(d[0][\"id\"])")" ]'
gcurl -s -o /dev/null -X POST -H "Authorization: Bearer $NT " " $G /api/v1/follow_requests/ $( gcurl -s -H "Authorization: Bearer $NT " " $G /api/v1/follow_requests" | j "print(d[0]['id'])" ) /authorize"
until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$new_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \
&& ok "the new account lets alice in" || ko "the new account never accepted alice"