Utility Scripts for the Synapse Admin API
A bunch of scripts easing up admin tasks and bigger API usage. For example: - login/logout of a user and saving the credentials to a file - querying a matrix server for account data - local filtering operations on the account data for rooms and users - deleting users via admin API based on the filtered data - deleting rooms via admin API based on the filtered datamain
commit
effa70c19d
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
input_file=$1
|
||||
output_file=$3
|
||||
pattern=$2
|
||||
|
||||
if [ -z $input_file -o -z $pattern ]; then
|
||||
echo "input file: $input_file, pattern: $pattern"
|
||||
echo "Usage: $0 <./path/to/matrix-rooms.txt> <PATTERN> [./path/to/output.txt]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#echo "Converting matrix account data into a comprehensive room list ..."
|
||||
if [ -z $output_file ]; then
|
||||
jq ".rooms.join | [to_entries[] | {\"room_id\": .key, \"room_name\": .value.state.events[] | select(.type == \"m.room.name\").content.name, \"users\": [.value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}]} | select(.users[].displayname | match(\"$pattern\")?)] | group_by(.room_id) | map({room_id: .[0].room_id, room_name: .[0].room_name, matches: length, users: .[0].users})" "$input_file"
|
||||
|
||||
|
||||
else
|
||||
jq ".rooms.join | [to_entries[] | {\"room_id\": .key, \"room_name\": .value.state.events[] | select(.type == \"m.room.name\").content.name, \"users\": [.value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}]} | select(.users[].displayname | match(\"$pattern\")?)] | group_by(.room_id) | map({room_id: .[0].room_id, room_name: .[0].room_name, matches: length, users: .[0].users})" "$input_file" > $output_file
|
||||
fi
|
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
input_file=$1
|
||||
output_file=$3
|
||||
pattern=$2
|
||||
|
||||
if [ -z $input_file -o -z $pattern ]; then
|
||||
echo "input file: $input_file, pattern: $pattern"
|
||||
echo "Usage: $0 <./path/to/matrix-rooms.txt> <PATTERN> [./path/to/output.txt]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Converting matrix account data into a comprehensive room list ..."
|
||||
if [ -z $output_file ]; then
|
||||
jq ".rooms.join | [to_entries[] | {\"room_id\": .key, \"room_name\": .value.state.events[] | select(.type == \"m.room.name\").content.name} | select(.room_name | match(\"$pattern\"))]" $input_file
|
||||
else
|
||||
jq ".rooms.join | [to_entries[] | {\"room_id\": .key, \"room_name\": .value.state.events[] | select(.type == \"m.room.name\").content.name} | select(.room_name | match(\"$pattern\"))]" $input_file > $output_file
|
||||
fi
|
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
input_file=$1
|
||||
output_file=$3
|
||||
pattern=$2
|
||||
|
||||
if [ -z $input_file -o -z $pattern ]; then
|
||||
echo "input file: $input_file, pattern: $pattern"
|
||||
echo "Usage: $0 <./path/to/matrix-rooms.txt> <PATTERN> [./path/to/output.txt]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#echo "Converting matrix account data into a comprehensive room list ..."
|
||||
if [ -z $output_file ]; then
|
||||
jq ".rooms.join | [to_entries[] | {\"room_id\": .key, \"room_name\": .value.state.events[] | select(.type == \"m.room.name\").content.name, \"users\": [.value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}]} | select(.users[].user_id | match(\"$pattern\"))] | group_by(.room_id) | map({room_id: .[0].room_id, room_name: .[0].room_name, matches: length, users: .[0].users})" "$input_file"
|
||||
|
||||
|
||||
else
|
||||
jq ".rooms.join | [to_entries[] | {\"room_id\": .key, \"room_name\": .value.state.events[] | select(.type == \"m.room.name\").content.name, \"users\": [.value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}]} | select(.users[].user_id | match(\"$pattern\"))] | group_by(.room_id) | map({room_id: .[0].room_id, room_name: .[0].room_name, matches: length, users: .[0].users})" "$input_file" > $output_file
|
||||
fi
|
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
input_file=$1
|
||||
output_file=$3
|
||||
pattern=$2
|
||||
|
||||
if [ -z $input_file -o -z $pattern ]; then
|
||||
echo "input file: $input_file, pattern: $pattern"
|
||||
echo "Usage: $0 <./path/to/matrix-rooms.txt> <PATTERN> [./path/to/output.txt]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#echo "Converting matrix account data into a comprehensive room list ..."
|
||||
if [ -z $output_file ]; then
|
||||
jq ".rooms.join | [to_entries[] | .value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}] | unique_by(.user_id) | map(select(.displayname | match(\"$pattern\")?))" "$input_file"
|
||||
|
||||
else
|
||||
jq ".rooms.join | [to_entries[] | .value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}] | unique_by(.user_id) | map(select(.displayname | match(\"$pattern\")?))" "$input_file" > "$output_file"
|
||||
fi
|
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
input_file=$1
|
||||
output_file=$3
|
||||
pattern=$2
|
||||
|
||||
if [ -z $input_file -o -z $pattern ]; then
|
||||
echo "input file: $input_file, pattern: $pattern"
|
||||
echo "Usage: $0 <./path/to/matrix-rooms.txt> <PATTERN> [./path/to/output.txt]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#echo "Converting matrix account data into a comprehensive room list ..."
|
||||
if [ -z $output_file ]; then
|
||||
jq ".rooms.join | [to_entries[] | .value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}] | unique_by(.user_id) | map(select(.user_id | match(\"$pattern\")))" "$input_file"
|
||||
|
||||
else
|
||||
jq ".rooms.join | [to_entries[] | .value.state.events[] | select(.type == \"m.room.member\") | {\"user_id\": .sender, \"displayname\": .content.displayname}] | unique_by(.user_id) | map(select(.user_id | match(\"$pattern\")))" "$input_file" > "$output_file"
|
||||
fi
|
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
domain=$1
|
||||
output_file=$2
|
||||
read -p "User: " user
|
||||
read -p "Password: " password
|
||||
|
||||
if [ -e $output_file ]; then
|
||||
output_file=matrix-login.txt
|
||||
fi
|
||||
|
||||
if [ -z $domain -o -z $user -o -z $password ]; then
|
||||
echo "Domain: $domain, User: $user, Password: $password"
|
||||
echo "Usage: $0 \"https://matrix.server\" <OUTPUT_FILE>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Querying homeserver for new login data ..."
|
||||
echo curl -XPOST -d "{\"type\":\"m.login.password\", \"user\":\"$user\", \"password\":\"$password\"}" "$domain/_matrix/client/r0/login" -o "$output_file"
|
||||
curl -XPOST -d "{\"type\":\"m.login.password\", \"user\":\"$user\", \"password\":\"$password\"}" "$domain/_matrix/client/r0/login" -o "$output_file"
|
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
domain=$1
|
||||
login_data=$2
|
||||
|
||||
|
||||
if [ -z $domain -o -z $login_data ]; then
|
||||
echo "Usage: $0 \"https://matrix.server\" <LOGIN_FILE>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
token=$(cat $login_data | jq -r '.access_token')
|
||||
|
||||
echo "Logging user out ..."
|
||||
curl -XPOST -H "Authorization: Bearer $token" "$domain/_matrix/client/r0/logout"
|
@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
#'
|
||||
#This Bash script takes a json array of form [{"room_id": "!asdX:domain.com", "room_name": "nameX"}, {"room_id": "!asdY:domain.com", "room_name": "nameY"}] and iterates over them with the delete room api which is exclusive to Synapse.
|
||||
#This array is supplied as a file parameter and created with another script (see filter_account_data_rooms_for_pattern.sh)
|
||||
#
|
||||
#See: https://matrix-org.github.io/synapse/latest/admin_api/rooms.html#delete-room-api
|
||||
#
|
||||
#'
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
domain=$1
|
||||
login_file=$2
|
||||
input_file=$3
|
||||
output_folder=$4
|
||||
|
||||
if [ -z "$domain" -o ! -e "$input_file" -o ! -e "$login_file" ]; then
|
||||
echo "Domain: $domain, login file: $login_file, input file: $input_file, output folder: $output_folder"
|
||||
echo "Usage: $0 http(s)://<DOMAIN> <LOGIN_FILE> <INPUT_FILE> [OUTPUT_FOLDER]"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -z "$output_folder" -a ! -d "$output_folder" ]; then
|
||||
echo "The given output folder ($output_folder) is not a valid directory! Creating it ..."
|
||||
mkdir $output_folder
|
||||
fi
|
||||
|
||||
#echo "Querying homeserver for new login data ..."
|
||||
#echo curl -XPOST -d "{\"type\":\"m.login.password\", \"user\":\"$user\", \"password\":\"$password\"}" "$domain/_matrix/client/r0/login" -o "$output_file"
|
||||
#curl --globoff -XGET -H "Authorization: Bearer $token" "$domain/_matrix/client/r0/sync?filter={\"room\":{\"timeline\":{\"limit\":1}}}"
|
||||
|
||||
ROOM_COUNT=$(jq '. | length' "$input_file")
|
||||
echo "Found $ROOM_COUNT rooms to delete in the input file. Example: "
|
||||
echo $(jq '.[0]' "$input_file")
|
||||
echo
|
||||
echo "Other Example: "
|
||||
echo $(jq '.[-1]' "$input_file")
|
||||
echo
|
||||
|
||||
read -p "Is this looking correct? (y/n) " reply
|
||||
if [ "$reply" != "y" -a "$reply" != "Y" ]; then
|
||||
echo "Aborting ..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
token=$(jq -r '.access_token' "$login_file")
|
||||
|
||||
|
||||
for ((i = 0; i < $ROOM_COUNT; i++ ));do
|
||||
room_json=$(jq ".[$i]" "$input_file")
|
||||
room_name=$(echo $room_json | jq -r '.room_name')
|
||||
room_id=$(echo $room_json | jq -r '.room_id')
|
||||
room_id_enc=$(echo $room_json | jq -r '.room_id' | sed 's/!/%21/g' | sed 's/:/%3A/g') # room id has to be URL encoded (bootleg version)
|
||||
echo "Currently purging room $room_name with ID: $room_id ..."
|
||||
|
||||
if [ -d "$output_folder" ]; then
|
||||
output_file="$output_folder/$room_id_enc-delete_result.txt"
|
||||
fi
|
||||
|
||||
if [ ! -z "$output_file" ]; then
|
||||
echo curl --globoff -XDELETE -H "Authorization: Bearer $token" -d "{\"block\": false, \"purge\": true}" "$domain/_synapse/admin/v2/rooms/$room_id_enc" -o "$output_file"
|
||||
curl --globoff -XDELETE -H "Authorization: Bearer $token" -d "{\"block\": false, \"purge\": true}" "$domain/_synapse/admin/v2/rooms/$room_id_enc" -o "$output_file"
|
||||
else
|
||||
echo curl --globoff -XDELETE -H "Authorization: Bearer $token" -d "{\"block\": false, \"purge\": true}" "$domain/_synapse/admin/v2/rooms/$room_id_enc"
|
||||
curl --globoff -XDELETE -H "Authorization: Bearer $token" -d "{\"block\": false, \"purge\": true}" "$domain/_synapse/admin/v2/rooms/$room_id_enc"
|
||||
fi
|
||||
|
||||
echo "Sleeping for 5 seconds ..."
|
||||
sleep 5
|
||||
|
||||
done
|
@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
#'
|
||||
#This Bash script takes a json array of form [{"user_id": "@asdX:domain.com", "displayname": "nameX"}, {"user_id": "@asdY:domain.com", "displayname": null}] and iterates over them with the delete user api which is exclusive to Synapse.
|
||||
#This array is supplied as a file parameter and created with another script (see filter_users_by_*.sh)
|
||||
#
|
||||
#See: https://matrix-org.github.io/synapse/latest/admin_api/user_admin_api.html#deactivate-account
|
||||
#
|
||||
#'
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
domain=$1
|
||||
login_file=$2
|
||||
input_file=$3
|
||||
output_folder=$4
|
||||
|
||||
if [ -z "$domain" -o ! -e "$input_file" -o ! -e "$login_file" ]; then
|
||||
echo "Domain: $domain, login file: $login_file, input file: $input_file, output folder: $output_folder"
|
||||
echo "Usage: $0 http(s)://<DOMAIN> <LOGIN_FILE> <INPUT_FILE> [OUTPUT_FOLDER]"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -z "$output_folder" -a ! -d "$output_folder" ]; then
|
||||
echo "The given output folder ($output_folder) is not a valid directory! Creating it ..."
|
||||
mkdir $output_folder
|
||||
fi
|
||||
|
||||
USER_COUNT=$(jq '. | length' "$input_file")
|
||||
echo "Found $USER_COUNT users to delete in the input file. Example: "
|
||||
echo $(jq '.[0]' "$input_file")
|
||||
echo
|
||||
echo "Other Example: "
|
||||
echo $(jq '.[-1]' "$input_file")
|
||||
echo
|
||||
|
||||
read -p "Is this looking correct? (y/n) " reply
|
||||
if [ "$reply" != "y" -a "$reply" != "Y" ]; then
|
||||
echo "Aborting ..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
token=$(jq -r '.access_token' "$login_file")
|
||||
|
||||
|
||||
for ((i = 0; i < $USER_COUNT; i++ ));do
|
||||
user_json=$(jq ".[$i]" "$input_file")
|
||||
user_displayname=$(echo $user_json | jq -r '.displayname')
|
||||
user_id=$(echo $user_json | jq -r '.user_id')
|
||||
user_id_enc=$(echo $user_json | jq -r '.user_id' | sed 's/@/%40/g' | sed 's/:/%3A/g') # user id has to be URL encoded (bootleg version)
|
||||
echo "Currently purging user $user_displayname with ID: $user_id ..."
|
||||
|
||||
if [ -d "$output_folder" ]; then
|
||||
output_file="$output_folder/$user_id_enc-delete_result.txt"
|
||||
fi
|
||||
|
||||
if [ ! -z "$output_file" ]; then
|
||||
echo curl --globoff -XDELETE -H "Authorization: Bearer [TOKEN]" -d "{\"erase\": true}" "$domain/_synapse/admin/v1/deactivate/$user_id_enc" -o "$output_file"
|
||||
curl --globoff -XDELETE -H "Authorization: Bearer $token" -d "{\"erase\": true}" "$domain/_synapse/admin/v1/deactivate/$user_id_enc" -o "$output_file"
|
||||
else
|
||||
echo curl --globoff -XDELETE -H "Authorization: Bearer [TOKEN]" -d "{\"erase\": true}" "$domain/_synapse/admin/v1/deactivate/$user_id_enc"
|
||||
curl --globoff -XDELETE -H "Authorization: Bearer $token" -d "{\"erase\": true}" "$domain/_synapse/admin/v1/deactivate/$user_id_enc"
|
||||
fi
|
||||
|
||||
echo "Sleeping for 5 seconds ..."
|
||||
sleep 5
|
||||
|
||||
done
|
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
domain=$2
|
||||
login_data=$1
|
||||
output_file=$3
|
||||
|
||||
if [ -z $output_file ]; then
|
||||
output_file=matrix-rooms.txt
|
||||
fi
|
||||
|
||||
if [ -z $domain -o ! -f $login_data ]; then
|
||||
echo "domain: $domain login: $login_data"
|
||||
echo "Usage: $0 ./path/to/matrix-login.txt \"https://matrix.server\""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
token=$(cat $login_data | jq -r '.access_token')
|
||||
|
||||
# Queries for a list of room IDs
|
||||
# jq '.rooms.join'
|
||||
|
||||
# Querying for a list of displaynames
|
||||
# TODO why are there null's in the list?
|
||||
# TODO how do I ALSO get the room ID?
|
||||
# TODO can I just select() in jq to select the room IDs?
|
||||
# jq '.rooms.join | .[].state.events[].content.channel' matrix-rooms.txt | grep -v null | less
|
||||
|
||||
# Lists all room names out of the m.room.name state event as an array
|
||||
# jq '.rooms.join | [.[].state.events[] | select(.type == "m.room.name").content.name]'
|
||||
|
||||
# List all room IDs with room names as objects {"room_name": x, "room_id": y}
|
||||
# jq '.rooms.join | to_entries[] | {"room_id": .key, "room_name": .value.state.events[] | select(.type == "m.room.name").content.name}'
|
||||
|
||||
|
||||
|
||||
echo "Querying homeserver for room data. This might take a while ..."
|
||||
echo curl --globoff -XGET -H "Authorization: Bearer [YOUR TOKEN]" "$domain/_matrix/client/r0/sync?filter={"room":{"timeline":{"limit":1}}}" -o "$output_file"
|
||||
curl --globoff -XGET -H "Authorization: Bearer $token" "$domain/_matrix/client/r0/sync?filter={\"room\":{\"timeline\":{\"limit\":1}}}" -o "$output_file"
|
Loading…
Reference in New Issue