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