Compare commits

...

50 Commits
v0.22.0 ... dev

Author SHA1 Message Date
Joe 00d62d6f88
revert change to event reports output formatting 2024-02-28 21:35:35 -06:00
Joe eb02dace21
explain project status in readme 2024-02-28 19:03:40 -06:00
Joe 15411d68e9
bump version 2023-11-19 10:40:19 -06:00
Joe 107b019df2
remove 'shuf' from dependency check as it is no longer necessary 2023-11-19 10:39:37 -06:00
Joe a7d934209f
bump version 2023-09-29 11:26:14 -05:00
Joe 65e4042667
add untracked SynapseEventReportsDelete, fixes #46 2023-09-29 11:25:37 -05:00
Joe 92f57694d4
[ci] add gpg key passphrase to drone release pipeline 2023-09-24 18:40:24 -05:00
Joe 9911b177c5
bump version 2023-08-09 08:07:33 -05:00
Joe 044f3001bf
escape double-quotes in room delete message body 2023-07-29 17:42:55 -05:00
Joe d25a4f965a
add support for deleting event reports 2023-07-29 17:42:11 -05:00
Joe cb27a307e7
use utility function to generate random part of device ID instead of external programs 2023-07-29 17:30:49 -05:00
Joe 25336f2aa6
don't attempt to redefine Matrix params 2023-07-29 17:29:22 -05:00
Joe 58a48dfeb1
improve debug logging output when reading config 2023-07-29 17:27:35 -05:00
Joe f529bcf4ef
use local variable when reading config file 2023-07-29 17:26:46 -05:00
Joe 5781001c29
log response body on success if log level is DEBUG 2023-07-29 17:25:01 -05:00
Joe d7ed574914
add some comments to Request function 2023-07-29 17:23:58 -05:00
Joe d1716632f3
bump version 2023-01-18 15:07:00 -06:00
Joe 77f320e4dd
don't attempt to redefine Synapse endpoints 2023-01-18 15:06:31 -06:00
Joe 863901ccf9
validate input as integers (#30) 2023-01-16 14:37:26 -06:00
Joe 95c76a0a13
mark obviously immutable variables as readonly, closes #41 2023-01-16 14:22:00 -06:00
Joe a3ed8ba2e0
bump version 2023-01-12 12:13:54 -06:00
Joe 0d868db40b
declare various input vars locally to avoid polluting global scope 2023-01-12 12:13:16 -06:00
Joe eed7f38fe1
add missing double quotes 2023-01-12 12:11:52 -06:00
Joe d7dfc59547
correct test syntax for validating hosts 2023-01-12 11:40:57 -06:00
Joe 4c9ffc49cb
bump version 2023-01-12 09:50:48 -06:00
Joe 48c80db050
properly set path parameter when getting forward extremities 2023-01-12 09:49:57 -06:00
Joe ed6e45022b
bump version 2023-01-12 08:17:49 -06:00
Joe 93a77faa46
eliminate nested functions, closes #39 2023-01-12 08:17:28 -06:00
Joe d7d113b9e1
bump version 2023-01-12 07:48:12 -06:00
Joe df55392c3a
update copyright notice 2023-01-12 07:47:48 -06:00
Joe 2f7ff4a739
update build file 2023-01-12 07:47:21 -06:00
Joe 0b37840e01
refactor Synapse API functions to new body parameter handling pattern, closes #40 2023-01-12 07:46:56 -06:00
Joe 373830fba3
update Matrix parameter definitions 2023-01-12 07:45:32 -06:00
Joe c512fe0acc
define Matrix endpoints and parameters via the main function 2023-01-12 07:44:54 -06:00
Joe e0cd0e79f7
update Matrix endpoint definitions 2023-01-12 07:44:07 -06:00
Joe d5fca49ce9
refactor Matrix API functions to use new pattern (#40) 2023-01-12 07:33:21 -06:00
Joe 18cd059575
use body parameter map passed as reference instead of global map in ConstructObject (#40) 2023-01-12 07:32:00 -06:00
Joe 9ced833dfa
refactor Synapse API functions to use new pattern (#40) 2023-01-11 16:13:02 -06:00
Joe f2f9ea52fb
URL encode path parameters 2023-01-11 14:58:42 -06:00
Joe cddb481423
refactor Synapse API functions to remove nested functions, closes #42 2023-01-11 14:46:17 -06:00
Joe 9cf29ab12c
refactor Matrix API functions to remove nested functions (#42) 2023-01-11 14:25:21 -06:00
Joe af2d671c41
add function to set endpoint path parameters (#40) 2023-01-11 14:11:40 -06:00
Joe 6c1e911a84
refactor SynapseEventReports using new pattern (#40, #42) 2023-01-11 13:07:12 -06:00
Joe f5e87823e1
add utility function to copy arrays (#40) 2023-01-11 12:37:56 -06:00
Joe 0065472abd
add function to set query string for URL (#40) 2023-01-11 12:33:16 -06:00
Joe 53c3abcf48
validate destination input 2022-12-26 17:42:40 -06:00
Joe 68ee688568
add input validation function 2022-12-26 17:40:47 -06:00
Joe 0509da62c0
bump version 2022-11-19 06:12:25 -06:00
Joe 7643183e7a
don't describe threepid lookup arguments as required 2022-11-19 06:11:57 -06:00
Joe b9c4448597
update readme 2022-11-18 03:27:48 -06:00
56 changed files with 1281 additions and 888 deletions

View File

@ -20,6 +20,8 @@ steps:
settings:
key:
from_secret: gpg_key
passphrase:
from_secret: key_passphrase
files:
- axon.sh
detach_sign: true

View File

@ -3,7 +3,11 @@
[![License](https://shields.thisisjoes.site/badge/dynamic/json.svg?label=license&color=red&url=https://git.thisisjoes.site/api/v1/repos/joe/axon.sh/labels/@license&query=$.description)](https://git.thisisjoes.site/joe/axon.sh/src/branch/dev/LICENSE)
[![Latest Release](https://shields.thisisjoes.site/badge/dynamic/json.svg?label=latest%20release&color=green&url=https://git.thisisjoes.site/api/v1/repos/joe/axon.sh/releases&query=$[0].tag_name)](https://git.thisisjoes.site/joe/axon.sh/releases)
A Matrix Synapse administration tool written in bash. In early development.
A Matrix Synapse administration tool written in bash. In early development, but works pretty well!
## Project status
Due partly to a lack of interest from the wider homeserver admin community axon.sh's development has significantly slowed. The program does basically everything I personally need it to do to administrate my homeservers.
Pull requests and issues are still welcome, but barring specific feature requests or contributions, axon.sh will likely never completely support Synapse's admin API.
## Supported operations
#### Session management
@ -13,6 +17,7 @@ A Matrix Synapse administration tool written in bash. In early development.
#### Homeserver operations
- getting server version information
- getting event reports
- sending server notices
#### Federation operations
@ -30,6 +35,7 @@ A Matrix Synapse administration tool written in bash. In early development.
#### User operations
- getting list of joined rooms for user
- looking up user by third-party ID (3PID)
- resetting password for user
- creating new users
- deactivating users

View File

@ -9,6 +9,7 @@ json/
matrix/
synapse/
cmd/
input/
Help
PrintInfo
Prompt

View File

@ -1,5 +1,5 @@
projectName=axon.sh
projectDescription="A Matrix Synapse administration tool written in bash"
projectVersion=0.22.0
projectVersion=0.23.7
projectAuthor="joe <joe@thisisjoes.site>"
projectLicense=GPLv3

View File

@ -6,7 +6,6 @@ CheckDependencies() {
dependencies=(
curl
date
shuf
jq
)

View File

@ -58,11 +58,11 @@ Help() {
echo ' deactivate Deactivates a user. Optionally erases the user'\''s profile.'
echo ' shadowban Shadowbans a user.'
echo ' rooms Shows all rooms a user is currently a member of.'
echo ' threepid <medium> <address>'
echo ' threepid [medium] [address]'
echo ' Returns the MXID of the user associated with the given third-party ID (3PID).'
echo ' Required arguments:'
echo ' <medium> The medium of the 3PID, e.g. `email`.'
echo ' <address> The address of the 3PID, e.g. `user@example.com`.'
echo ' Optional arguments:'
echo ' [medium] The medium of the 3PID, e.g. `email`.'
echo ' [address] The address of the 3PID, e.g. `user@example.com`.'
echo ' ratelimit [set or delete] [username] [messages per second] [burst count]'
echo ' Returns the ratelimit override for the given user.'
echo ' Optional arguments:'

View File

@ -12,6 +12,8 @@ Main() {
WriteConfiguration
DefineStatusCodes
DefineObjects
DefineMatrixParams
DefineMatrixEndpoints
DefineSynapseParams
DefineSynapseEndpoints
CheckDependencies

View File

@ -1,7 +1,7 @@
PrintInfo() {
local info="$1"
case "$info" in
short ) echo "${projectName} Copyright (C) 2021-2022 ${projectAuthor}"
short ) echo "${projectName} Copyright (C) 2021-2023 ${projectAuthor}"
echo -e "\nThis program comes with ABSOLUTELY NO WARRANTY; for details type 'warranty'."
echo -e "\nThis is free software, and you are welcome to redistribute it under certain conditions;"
echo "type 'conditions' for details."

View File

@ -7,6 +7,7 @@ Prompt() {
history -n || Log warn "Failed to load history from '$HISTFILE'"
while true; do
local prompt="[axon]>"
local -a prompt_input
Read -e -r -p "$prompt" -a prompt_input
history -s "${prompt_input[@]}" || Log warn "Failed to append entry to history"
history -w || Log warn "Failed to write history to '$HISTFILE'"

View File

@ -4,13 +4,15 @@
ReadConfiguration() {
if [[ -f "${config[config_path]}/${config[config_file]}" ]]; then
Log config "Found configuration file."
local line
while read -r line; do
Log debug "Line is '$line'"
if [[ "$line" =~ '=' ]]; then
Log debug "line is '$line'"
Log debug "This looks like config to me..."
key="${line%%=*}"
Log debug "key is '$key'"
Log debug "Key is '$key'"
value="${line##*=}"
Log debug "value is '$value'"
Log debug "Value is '$value'"
config[$key]="$value"
fi
done < "${config[config_path]}/${config[config_file]}"

View File

@ -1,52 +1,45 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
DefineMatrixEndpoints() {
declare -Ag m_login_api
declare -Ag m_logout_api
declare -Ag m_whoami_api
declare -Ag m_resolve_alias_api
declare -Ag m_create_alias_api
declare -Ag m_delete_alias_api
m_login_api=(
declare -Agr m_login_api=(
[method]="POST"
[path]="/_matrix/client/r0/login"
[url_params]=""
[body_params]="m_login_params"
)
m_logout_api=(
declare -Agr m_logout_api=(
[method]="POST"
[path]="/_matrix/client/r0/logout"
[url_params]=""
[body_params]=""
)
m_whoami_api=(
declare -Agr m_whoami_api=(
[method]="GET"
[path]="/_matrix/client/r0/account/whoami"
[url_params]=""
[body_params]=""
)
m_resolve_alias_api=(
declare -Agr m_resolve_alias_api=(
[method]="GET"
[path]="/_matrix/client/r0/directory/room/${m_resolve_alias_url_params[alias]}"
[path]="/_matrix/client/r0/directory/room/ALIAS"
[url_params]="m_resolve_alias_url_params"
[body_params]=""
)
m_create_alias_api=(
declare -Agr m_create_alias_api=(
[method]="PUT"
[path]="/_matrix/client/r0/directory/room/${m_create_alias_url_params[alias]}"
[path]="/_matrix/client/r0/directory/room/ALIAS"
[url_params]="m_create_alias_url_params"
[body_params]="m_create_alias_body_params"
)
m_delete_alias_api=(
declare -Agr m_delete_alias_api=(
[method]="DELETE"
[path]="/_matrix/client/r0/directory/room/${m_delete_alias_url_params[alias]}"
[path]="/_matrix/client/r0/directory/room/ALIAS"
[url_params]="m_delete_alias_url_params"
[body_params]=""
)

View File

@ -1,35 +1,28 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site># SPDX-License-Identifier: GPL-3.0-only
DefineMatrixParams() {
declare -Ag m_login_params
declare -Ag m_resolve_alias_url_params
declare -Ag m_create_alias_url_params
declare -Ag m_create_alias_body_params
declare -Ag m_delete_alias_url_params
m_login_params=(
declare -Agr m_login_body_params=(
[type]="m.login.password"
[identifier]="m.id.user"
[user]="${config[admin_user]}"
[password]="$admin_password"
[token]="${config[admin_token]}"
[device_id]="${config[device_id]}"
[user]=""
[password]=""
[token]=""
[device_id]=""
)
m_resolve_alias_url_params=(
declare -Agr m_resolve_alias_url_params=(
[alias]=""
)
m_create_alias_url_params=(
declare -Agr m_create_alias_url_params=(
[alias]=""
)
m_create_alias_body_params=(
declare -Agr m_create_alias_body_params=(
[room_id]=""
)
m_delete_alias_url_params=(
declare -Agr m_delete_alias_url_params=(
[alias]=""
)
}

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-3.0-only
DefineObjects() {
m_login_object='
declare -gr m_login_object='
{
"type":"",
"identifier": {
@ -14,13 +14,13 @@ DefineObjects() {
}
'
m_create_alias_object='
declare -gr m_create_alias_object='
{
"room_id": ""
}
'
s_server_notice_object='
declare -gr s_server_notice_object='
{
"user_id": "",
"content": {
@ -29,14 +29,14 @@ DefineObjects() {
}
}
'
s_purge_history_object='
declare -gr s_purge_history_object='
{
"delete_local_events": false,
"purge_up_to_ts": 0
}
'
s_delete_room_object='
declare -gr s_delete_room_object='
{
"new_room_user_id": "",
"room_name": "",
@ -46,7 +46,7 @@ DefineObjects() {
}
'
s_user_create_object='
declare -gr s_user_create_object='
{
"password": "",
"displayname": "",
@ -54,21 +54,21 @@ DefineObjects() {
}
'
s_user_reset_password_object='
declare -gr s_user_reset_password_object='
{
"new_password": "",
"logout_devices": true
}
'
s_set_user_ratelimit_object='
declare -gr s_set_user_ratelimit_object='
{
"messages_per_second": 0,
"burst_count": 0
}
'
s_user_deactivate_object='
declare -gr s_user_deactivate_object='
{
"erase": false
}

View File

@ -1,6 +1,5 @@
DefineStatusCodes() {
declare -Ag http_status_codes
http_status_codes=(
declare -Agr http_status_codes=(
[100]="Continue"
[101]="Switching Protocol"
[102]="Processing"

View File

@ -1,187 +1,172 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
DefineSynapseEndpoints() {
declare -Ag s_version_api
declare -Ag s_destination_details_api
declare -Ag s_destination_reset_api
declare -Ag s_server_notice_api
declare -Ag s_event_reports_api
declare -Ag s_purge_history_api
declare -Ag s_purge_history_status_api
declare -Ag s_delete_room_api
declare -Ag s_delete_room_status_api
declare -Ag s_forward_extremities_api
declare -Ag s_delete_forward_extremities_api
declare -Ag s_user_query_api
declare -Ag s_user_joined_rooms_api
declare -Ag s_user_threepid_lookup_api
declare -Ag s_user_create_api
declare -Ag s_user_reset_password_api
declare -Ag s_user_ratelimit_api
declare -Ag s_set_user_ratelimit_api
declare -Ag s_delete_user_ratelimit_api
declare -Ag s_user_shadowban_api
declare -Ag s_room_membership_api
declare -Ag s_user_deactivate_api
s_version_api=(
declare -Agr s_version_api=(
[method]="GET"
[path]="/_synapse/admin/v1/server_version"
[url_params]=""
[body_params]=""
)
s_destination_details_api=(
declare -Agr s_destination_details_api=(
[method]="GET"
[path]="/_synapse/admin/v1/federation/destinations/${s_destination_details_url_params[destination]}"
[path]="/_synapse/admin/v1/federation/destinations/DESTINATION"
[url_params]="s_destination_details_url_params"
[body_params]=""
)
s_destination_reset_api=(
declare -Agr s_destination_reset_api=(
[method]="POST"
[path]="/_synapse/admin/v1/federation/destinations/${s_destination_reset_url_params[destination]}/reset_connection"
[path]="/_synapse/admin/v1/federation/destinations/DESTINATION/reset_connection"
[url_params]="s_destination_reset_url_params"
[body_params]=""
[minimum_version]="1.52.0rc1"
)
s_server_notice_api=(
declare -Agr s_server_notice_api=(
[method]="POST"
[path]="/_synapse/admin/v1/send_server_notice"
[url_params]=""
[body_params]="s_server_notice_body_params"
)
s_event_reports_api=(
declare -Agr s_event_reports_api=(
[method]="GET"
[path]="/_synapse/admin/v1/event_reports?from=${s_event_reports_url_params[from]}&limit=${s_event_reports_url_params[limit]}&dir=${s_event_reports_url_params[dir]}"
[path]="/_synapse/admin/v1/event_reports"
[url_params]="s_event_reports_url_params"
[body_params]=""
)
s_purge_history_api=(
declare -Agr s_event_reports_delete_api=(
[method]="DELETE"
[path]="/_synapse/admin/v1/event_reports/REPORT_ID"
[url_params]="s_event_reports_delete_url_params"
[body_params]=""
[minimum_version]="1.79.0rc1"
)
declare -Agr s_purge_history_api=(
[method]="POST"
[path]="/_synapse/admin/v1/purge_history/${s_purge_history_url_params[room_id]}"
[path]="/_synapse/admin/v1/purge_history/ROOM_ID"
[url_params]="s_purge_history_url_params"
[body_params]="s_purge_history_body_params"
)
s_purge_history_status_api=(
declare -Agr s_purge_history_status_api=(
[method]="GET"
[path]="/_synapse/admin/v1/purge_history_status/${s_purge_history_status_url_params[job_id]}"
[path]="/_synapse/admin/v1/purge_history_status/JOB_ID"
[url_params]="s_purge_history_status_url_params"
[body_params]=""
)
s_delete_room_api=(
declare -Agr s_delete_room_api=(
[method]="DELETE"
[path]="/_synapse/admin/v2/rooms/${s_delete_room_url_params[room_id]}"
[path]="/_synapse/admin/v2/rooms/ROOM_ID"
[url_params]="s_delete_room_url_params"
[body_params]="s_delete_room_body_params"
)
s_delete_room_status_api=(
declare -Agr s_delete_room_status_api=(
[method]="GET"
[path]="/_synapse/admin/v2/rooms/delete_status/${s_delete_room_status_url_params[job_id]}"
[path]="/_synapse/admin/v2/rooms/delete_status/JOB_ID"
[url_params]="s_delete_room_status_url_params"
[body_params]=""
)
s_forward_extremities_api=(
declare -Agr s_forward_extremities_api=(
[method]="GET"
[path]='/_synapse/admin/v1/rooms/'"${s_forward_extremities_url_params[room_id_or_alias]}"'/forward_extremities'
[path]='/_synapse/admin/v1/rooms/ROOM_ID_OR_ALIAS/forward_extremities'
[url_params]="s_forward_extremities_url_params"
[body_params]=""
[minimum_version]="1.27.0rc1"
)
s_delete_forward_extremities_api=(
declare -Agr s_delete_forward_extremities_api=(
[method]="DELETE"
[path]='/_synapse/admin/v1/rooms/'"${s_delete_forward_extremities_url_params[room_id_or_alias]}"'/forward_extremities'
[path]='/_synapse/admin/v1/rooms/ROOM_ID_OR_ALIAS/forward_extremities'
[url_params]="s_delete_forward_extremities_url_params"
[body_params]=""
[minimum_version]="1.27.0rc1"
)
s_user_query_api=(
declare -Agr s_user_query_api=(
[method]="GET"
[path]="/_synapse/admin/v2/users/${s_user_query_url_params[user_id]}"
[path]="/_synapse/admin/v2/users/USER_ID"
[url_params]="s_user_query_url_params"
[body_params]=""
)
s_user_joined_rooms_api=(
declare -Agr s_user_joined_rooms_api=(
[method]="GET"
[path]="/_synapse/admin/v1/users/${s_user_joined_rooms_url_params[user_id]}/joined_rooms"
[path]="/_synapse/admin/v1/users/USER_ID/joined_rooms"
[url_params]="s_user_joined_rooms_url_params"
[body_params]=""
)
s_user_threepid_lookup_api=(
declare -Agr s_user_threepid_lookup_api=(
[method]="GET"
[path]="/_synapse/admin/v1/threepid/${s_user_threepid_lookup_url_params[medium]}/users/${s_user_threepid_lookup_url_params[address]}"
[path]="/_synapse/admin/v1/threepid/MEDIUM/users/ADDRESS"
[url_params]="s_user_threepid_lookup_url_params"
[body_params]=""
[minimum_version]="1.72.0rc1"
)
s_user_create_api=(
declare -Agr s_user_create_api=(
[method]="PUT"
[path]="/_synapse/admin/v2/users/${s_user_create_url_params[user_id]}"
[path]="/_synapse/admin/v2/users/USER_ID"
[url_params]="s_user_create_url_params"
[body_params]="s_user_create_body_params"
)
s_user_reset_password_api=(
declare -Agr s_user_reset_password_api=(
[method]="POST"
[path]="/_synapse/admin/v1/reset_password/${s_user_reset_password_url_params[user_id]}"
[path]="/_synapse/admin/v1/reset_password/USER_ID"
[url_params]="s_user_reset_password_url_params"
[body_params]="s_user_reset_password_body_params"
)
s_user_ratelimit_api=(
declare -Agr s_user_ratelimit_api=(
[method]="GET"
[path]="/_synapse/admin/v1/users/${s_user_ratelimit_url_params[user_id]}/override_ratelimit"
[path]="/_synapse/admin/v1/users/USER_ID/override_ratelimit"
[url_params]="s_user_ratelimit_url_params"
[body_params]=""
[minimum_version]="1.32.0rc1"
)
s_set_user_ratelimit_api=(
declare -Agr s_set_user_ratelimit_api=(
[method]="POST"
[path]="/_synapse/admin/v1/users/${s_set_user_ratelimit_url_params[user_id]}/override_ratelimit"
[path]="/_synapse/admin/v1/users/USER_ID/override_ratelimit"
[url_params]="s_set_user_ratelimit_url_params"
[body_params]="s_set_user_ratelimit_body_params"
[minimum_version]="1.32.0rc1"
)
s_delete_user_ratelimit_api=(
declare -Agr s_delete_user_ratelimit_api=(
[method]="DELETE"
[path]="/_synapse/admin/v1/users/${s_delete_user_ratelimit_url_params[user_id]}/override_ratelimit"
[path]="/_synapse/admin/v1/users/USER_ID/override_ratelimit"
[url_params]="s_delete_user_ratelimit_url_params"
[body_params]=""
[minimum_version]="1.32.0rc1"
)
s_user_deactivate_api=(
declare -Agr s_user_deactivate_api=(
[method]="POST"
[path]="/_synapse/admin/v1/deactivate/${s_user_deactivate_url_params[user_id]}"
[path]="/_synapse/admin/v1/deactivate/USER_ID"
[url_params]="s_user_deactivate_url_params"
[body_params]="s_user_deactivate_body_params"
)
s_user_shadowban_api=(
declare -Agr s_user_shadowban_api=(
[method]="POST"
[path]="/_synapse/admin/v1/users/${s_user_shadowban_url_params[user_id]}/shadow_ban"
[path]="/_synapse/admin/v1/users/USER_ID/shadow_ban"
[url_params]="s_user_shadowban_url_params"
[body_params]=""
)
s_room_membership_api=(
declare -Agr s_room_membership_api=(
[method]="POST"
[path]="/_synapse/admin/v1/join/${s_room_membership_url_params[room_id_or_alias]}"
[path]="/_synapse/admin/v1/join/ROOM_ID_OR_ALIAS"
[url_params]="s_room_membership_url_params"
[body_params]=""
)

View File

@ -1,50 +1,23 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
DefineSynapseParams() {
declare -Ag s_server_notice_body_params
declare -Ag s_destination_details_url_params
declare -Ag s_destination_reset_url_params
declare -Ag s_event_reports_url_params
declare -Ag s_purge_history_url_params
declare -Ag s_purge_history_body_params
declare -Ag s_purge_history_status_url_params
declare -Ag s_delete_room_url_params
declare -Ag s_delete_room_body_params
declare -Ag s_delete_room_status_url_params
declare -Ag s_forward_extremities_url_params
declare -Ag s_delete_forward_extremities_url_params
declare -Ag s_user_query_url_params
declare -Ag s_user_threepid_lookup_url_params
declare -Ag s_user_joined_rooms_url_params
declare -Ag s_user_modify_body_params
declare -Ag s_user_create_url_params
declare -Ag s_user_create_body_params
declare -Ag s_user_reset_password_url_params
declare -Ag s_user_reset_password_body_params
declare -Ag s_user_ratelimit_url_params
declare -Ag s_set_user_ratelimit_url_params
declare -Ag s_set_user_ratelimit_body_params
declare -Ag s_delete_user_ratelimit_url_params
declare -Ag s_user_deactivate_url_params
declare -Ag s_user_deactivate_body_params
declare -Ag s_user_shadowban_url_params
s_server_notice_body_params=(
declare -Agr s_server_notice_body_params=(
[user_id]=""
[msg_type]="m.room.message"
[body]=""
)
s_destination_details_url_params=(
declare -Agr s_destination_details_url_params=(
[destination]=""
)
s_destination_reset_url_params=(
declare -Agr s_destination_reset_url_params=(
[destination]=""
)
s_event_reports_url_params=(
declare -Agr s_event_reports_url_params=(
[from]="0"
[limit]="3"
[dir]="b"
@ -52,24 +25,28 @@ DefineSynapseParams() {
[room_id]=""
)
s_purge_history_url_params=(
declare -Agr s_event_reports_delete_url_params=(
[report_id]=""
)
declare -Agr s_purge_history_url_params=(
[room_id]=""
)
s_purge_history_body_params=(
declare -Agr s_purge_history_body_params=(
[delete_local_events]="false"
[purge_up_to_ts]=""
)
s_purge_history_status_url_params=(
declare -Agr s_purge_history_status_url_params=(
[job_id]=""
)
s_delete_room_url_params=(
declare -Agr s_delete_room_url_params=(
[room_id]=""
)
s_delete_room_body_params=(
declare -Agr s_delete_room_body_params=(
[new_room_user_id]=""
[room_name]=""
[message]=""
@ -77,32 +54,32 @@ DefineSynapseParams() {
[purge]="false"
)
s_delete_room_status_url_params=(
declare -Agr s_delete_room_status_url_params=(
[job_id]=""
)
s_forward_extremities_url_params=(
declare -Agr s_forward_extremities_url_params=(
[room_id_or_alias]=""
)
s_delete_forward_extremities_url_params=(
declare -Agr s_delete_forward_extremities_url_params=(
[room_id_or_alias]=""
)
s_user_query_url_params=(
declare -Agr s_user_query_url_params=(
[user_id]=""
)
s_user_joined_rooms_url_params=(
declare -Agr s_user_joined_rooms_url_params=(
[user_id]=""
)
s_user_threepid_lookup_params=(
declare -Agr s_user_threepid_lookup_params=(
[medium]=""
[address]=""
)
s_user_modify_body_params=(
declare -Agr s_user_modify_body_params=(
[user_id]=""
[password]=""
[displayname]=""
@ -118,51 +95,51 @@ DefineSynapseParams() {
[order_dir]="f"
)
s_user_create_url_params=(
declare -Agr s_user_create_url_params=(
[user_id]=""
)
s_user_create_body_params=(
declare -Agr s_user_create_body_params=(
[password]=""
[displayname]=""
[admin]="false"
)
s_user_reset_password_url_params=(
declare -Agr s_user_reset_password_url_params=(
[user_id]=""
)
s_user_reset_password_body_params=(
declare -Agr s_user_reset_password_body_params=(
[password]=""
[logout]="true"
)
s_user_ratelimit_url_params=(
declare -Agr s_user_ratelimit_url_params=(
[user_id]=""
)
s_set_user_ratelimit_url_params=(
declare -Agr s_set_user_ratelimit_url_params=(
[user_id]=""
)
s_set_user_ratelimit_body_params=(
declare -Agr s_set_user_ratelimit_body_params=(
[messages_per_second]="0"
[burst_count]="0"
)
s_delete_user_ratelimit_url_params=(
declare -Agr s_delete_user_ratelimit_url_params=(
[user_id]=""
)
s_user_deactivate_url_params=(
declare -Agr s_user_deactivate_url_params=(
[user_id]=""
)
s_user_deactivate_body_params=(
declare -Agr s_user_deactivate_body_params=(
[erase]="false"
)
s_user_shadowban_url_params=(
declare -Agr s_user_shadowban_url_params=(
[user_id]=""
)
}

View File

@ -1,47 +1,35 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
CheckStatusCode() {
# local response_body="$1"
local status_code="$1"
Log info "Got HTTP status code '$status_code','${http_status_codes[$status_code]}' from '${config[homeserver]}'"
Informational() {
Log error "Server returned unsupported status code '$status_code'"
}
Successful() {
Log info "Server returned success, continuing..."
return 0
}
Redirect() {
Log error "Server returned unsupported status code '$status_code'"
return 1
}
ClientError() {
Log error "Server returned client error '$status_code','${http_status_codes[$status_code]}'"
return 1
}
ServerError() {
Log error "Server returned server error. '$status_code','${http_status_codes[$status_code]}'"
return 1
}
UnknownCode() {
Log error "Received malformed or unknown status code '$status_code'"
return 1
}
case "$status_code" in
1?? ) Informational;;
2?? ) Successful;;
3?? ) Redirect;;
4?? ) ClientError;;
5?? ) ServerError;;
* ) UnknownCode;;
1?? )
Log error "Server returned unsupported status code '$status_code'"
return 1
;;
2?? )
Log info "Server returned success, continuing..."
return 0
;;
3?? )
Log error "Server returned unsupported status code '$status_code'"
return 1
;;
4?? )
Log error "Server returned client error '$status_code','${http_status_codes[$status_code]}'"
return 1
;;
5?? )
Log error "Server returned server error. '$status_code','${http_status_codes[$status_code]}'"
return 1
;;
* )
Log error "Received malformed or unknown status code '$status_code'"
return 1
;;
esac
}

View File

@ -14,6 +14,7 @@ Request() {
local scheme="${config[scheme]}"
local port="${config[port]}"
# check for required parameters
local required_parameters=('method' 'path')
for parameter in "${required_parameters[@]}"; do
Log debug "Checking parameter '$parameter', value '${!parameter}'"
@ -23,13 +24,16 @@ Request() {
}
done
# if a host wasn't passed then use the configured default
if [[ -z "$host" ]]; then
host="${config[base_url]}"
fi
# construct the URI
local uri="$scheme://$host:$port$path"
Log info "Using method '$method' in request to '$uri'"
# construct the header arg
local -a header_arg=()
if [[ ! -z "${headers[*]}" ]]; then
for header in "${!headers[@]}"; do
@ -39,6 +43,7 @@ Request() {
Log debug "Constructed header arg '${header_arg[*]}'"
fi
# don't follow redirects unless asked to
if [[ "$redirect" == 'true' ]]; then
Log info "Following redirects for this request"
local redirect_arg="--location"
@ -46,6 +51,7 @@ Request() {
Log debug "Not following redirects for this request"
fi
# use auth unless asked not to
if [[ "$auth" == 'false' ]]; then
Log info "Not sending authorization header for this request"
else
@ -85,10 +91,12 @@ Request() {
return 1
fi
# clean up response
std_out="${std_out//[[:cntrl:]]/}"
std_out="${std_out//|/}"
std_out="${std_out/<+>/|}"
# separate response body from response code
local IFS="|"
read -r -a response <<< "$std_out"
local body="${response[0]}"
@ -97,9 +105,10 @@ Request() {
if CheckStatusCode "$status_code"; then
__Request_response_body="$body"
Log debug "Got body '${body:0:999}...'"
else
Log error "Request failed while using method '$method' in request to '$uri'."
Log debug "Got body '${body:0:255}'..."
Log debug "Got body '${body:0:255}...'"
__Request_response_body="$body"
return 1
fi

25
src/http/SetQueryString Normal file
View File

@ -0,0 +1,25 @@
# Copyright (C) 2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
SetQueryString() {
local -n __SetQueryString_parameters="$1"
Log debug "Parameters are '${__SetQueryString_parameters[*]}'"
local -n __SetQueryString_url="$2"
Log debug "URL is '$__SetQueryString_url'"
local counter='0'
local delimiter='?'
local query_string
local encoded_param
for param in "${!__SetQueryString_parameters[@]}"; do
# use correct delimiter if there is more than 1 parameter
(( $counter >= 1 )) && delimiter="&"
encoded_param="$( EncodeUrl "${__SetQueryString_parameters[$param]}" )"
Log debug "Encoded parameter is '$encoded_param'"
query_string+="${delimiter}${param}=${encoded_param}"
(( counter++ ))
done
Log debug "Query string is '$query_string'"
__SetQueryString_url+="$query_string"
}

65
src/input/ValidateInput Normal file
View File

@ -0,0 +1,65 @@
# Copyright (C) 2022-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
ValidateInput() {
local type="$1"
Log debug "Type is '$type'."
local input="$2"
Log debug "Input is '${input:0:63}'."
local -r hostname_pattern='^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$'
local -r ip_pattern='^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$'
case "$type" in
integer )
[[ "$input" =~ ^[[:digit:]]+$ ]] || {
Log error "Expected integer but got '$input'."
return 1
}
;;
boolean )
[[ "$input" =~ ^(true|false)$ ]] || {
Log error "Expected 'true' or 'false' but got '$input'."
return 1
}
;;
text )
[[ "$input" =~ ^[[:print:]]+$ ]] || {
Log error "Expected text but got something else."
return 1
}
;;
json )
ValidateJSON "$input" || {
Log error "Expected JSON but got something else. The output from jq above may help identify syntax errors."
return 1
}
;;
host )
[[ "$input" =~ $hostname_pattern || "$input" =~ $ip_pattern ]] || {
Log error "Expected hostname or IP literal but got '$input'."
return 1
}
;;
hostname )
[[ "$input" =~ $hostname_pattern ]] || {
Log error "Expected hostname but got '$input'."
return 1
}
;;
ip )
[[ "$input" =~ $ip_pattern ]] || {
Log error "Expected IP address but got '$input'."
return 1
}
;;
* ) Log error "Unknown type '$type'."; return 1 ;;
esac
}

View File

@ -1,4 +1,4 @@
# Copyright (C) 2022 joe <joe@thisisjoes.site>
# Copyright (C) 2022-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
ConstructObject() {
@ -6,11 +6,9 @@ ConstructObject() {
local object_to_construct="$1"
Log debug "Constructing object for '$object_to_construct'"
local -n __ConstructObject_object="$2"
local -n api="${object_to_construct}_api"
Log debug "Using parameters for API '${!api}'"
local -n parameters
parameters="${api[body_params]}"
local -n __ConstructObject_params="$2"
local -n __ConstructObject_object="$3"
local -n parameters="__ConstructObject_params"
local constructed_object
@ -53,6 +51,7 @@ ConstructObject() {
;;
s_delete_room )
parameters[message]="${parameters[message]//\"/\\\"}" # Escape double-quotes
local -a filters=(
".block = ${parameters[block]}"
".purge = ${parameters[purge]}"

View File

@ -1,4 +1,4 @@
# Copyright (C) 2022 joe <joe@thisisjoes.site>
# Copyright (C) 2022-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
MatrixCreateAlias() {
@ -6,25 +6,19 @@ MatrixCreateAlias() {
local alias="$1"
local room_id="$2"
DoCreateAlias() {
local object
ConstructObject m_create_alias object || return 1
local -A params=(
[method]="${m_create_alias_api[method]}"
[path]="${m_create_alias_api[path]}"
[data]="$object"
)
local response
Request params response || {
HandleMatrixError response
return 1
}
}
# copy api map to local map
local -A api
CopyArray m_create_alias_api api
# copy url parameters to local map
local -A url_params
CopyArray m_create_alias_url_params url_params
# copy body parameters to local map
local -A body_params
CopyArray m_create_alias_body_params body_params
CheckLoginStatus || return 1
DefineMatrixParams
# input
[[ ! -z "$alias" ]] || {
local input_alias
Read -r -p "$(echo -e -n '\nAlias to create:')" input_alias
@ -36,10 +30,25 @@ MatrixCreateAlias() {
Read -r -p "$(echo -e -n '\nRoom ID to link:')" input_room_id
room_id="$input_room_id"
}
m_create_alias_url_params[alias]="$(EncodeUrl "$alias")"
m_create_alias_body_params[room_id]="$room_id"
url_params[alias]="$alias"
body_params[room_id]="$room_id"
ReadConfiguration
DefineMatrixEndpoints
DoCreateAlias
SetPathParameters url_params api[path]
# construct request body
local object
ConstructObject m_create_alias body_params object || return 1
# set request parameters
local -A params=(
[method]="${api[method]}"
[path]="${api[path]}"
[data]="$object"
)
# make request
local response
Request params response || {
HandleMatrixError response
return 1
}
}

View File

@ -1,33 +1,38 @@
# Copyright (C) 2022 joe <joe@thisisjoes.site>
# Copyright (C) 2022-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
MatrixDeleteAlias() {
Log debug "Got args '$*'"
local alias="$1"
DoDeleteAlias() {
local -A params=(
[method]="${m_delete_alias_api[method]}"
[path]="${m_delete_alias_api[path]}"
)
local response
Request params response || {
HandleMatrixError response
return 1
}
}
# copy api map to local map
local -A api
CopyArray m_delete_alias_api api
# copy url parameters to local map
local -A url_params
CopyArray m_delete_alias_url_params url_params
CheckLoginStatus || return 1
DefineMatrixParams
# ask for alias if not passed
[[ ! -z "$alias" ]] || {
local input_alias
Read -r -p "$(echo -e -n '\nAlias to delete:')" input_alias
alias="$input_alias"
}
m_delete_alias_url_params[alias]="$(EncodeUrl "$alias")"
url_params[alias]="$alias"
ReadConfiguration
DefineMatrixEndpoints
DoDeleteAlias
SetPathParameters url_params api[path]
# set request parameters
local -A params=(
[method]="${api[method]}"
[path]="${api[path]}"
)
# make request
local response
Request params response || {
HandleMatrixError response
return 1
}
}

View File

@ -1,32 +1,17 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
MatrixLogin() {
Log debug "Got args '$*'"
DoLogin() {
local object
ConstructObject m_login object || return 1
local -A params=(
[method]="${m_login_api[method]}"
[path]="${m_login_api[path]}"
[data]="$object"
)
local response
Request params response || {
HandleMatrixError response
return 1
}
local -a keys=(access_token)
local -A values
ProcessResponse response keys values || return 1
config[admin_token]="${values[access_token]}"
WriteConfiguration
}
# copy api map to local map
local -A api
CopyArray m_login_api api
# copy body parameters to local map
local -A body_params
CopyArray m_login_body_params body_params
# input
local input_mxid
local localpart
local domainpart
@ -35,6 +20,7 @@ MatrixLogin() {
if [[ ! -z "$input_mxid" ]]; then
ParseMXID "$input_mxid" localpart domainpart || continue
config[admin_user]="$localpart"
body_params[user]="${config[admin_user]}"
config[homeserver]="$domainpart"
GetWellKnown "$domainpart" homeserver || continue
ParseServerName "$homeserver" host port
@ -47,7 +33,7 @@ MatrixLogin() {
local input_password
while Read -s -r -p "password:" input_password; do
if [[ ! -z "$input_password" ]]; then
admin_password="$input_password"
body_params[password]="$input_password"
break
else
echo
@ -55,22 +41,47 @@ MatrixLogin() {
fi
done
else
echo "Access token alReady present"
echo "Access token already present"
return 0;
fi
local input_save_token_pref
Read -r -p "$(echo -e -n '\nSave access token to local config file? (y/n)')" input_save_token_pref
case "$input_save_token_pref" in
[yY]|[Yy][Ee][Ss] ) config[save_token]="true";;
[Nn]|[Nn][Oo] ) config[save_token]="false";;
esac
GenDeviceId
body_params[device_id]="${config[device_id]}"
WriteConfiguration
ReadConfiguration
GenDeviceId
Log debug "Save ID preference is '${config[save_id]}'"
Log debug "Device ID is '${config[device_id]}'"
# construct request body
local object
ConstructObject m_login body_params object || return 1
# set request parameters
local -A params=(
[method]="${api[method]}"
[path]="${api[path]}"
[data]="$object"
)
# make request
local response
Request params response || {
HandleMatrixError response
return 1
}
# get key values
local -a keys=(access_token)
local -A values
ProcessResponse response keys values || return 1
# set token
config[admin_token]="${values[access_token]}"
WriteConfiguration
DefineMatrixEndpoints
DefineMatrixParams
DoLogin
}

View File

@ -1,26 +1,9 @@
# Copyright (C) 2021-2022 joe <joe@thisisjoes.site>
# Copyright (C) 2021-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
MatrixLogout() {
Log debug "Got args '$*'"
DoLogout() {
local -A params=(
[method]="${m_logout_api[method]}"
[path]="${m_logout_api[path]}"
)
local response
Request params response || {
HandleMatrixError response
return 1
}
config[admin_user]=""
config[admin_token]=""
config[device_id]=""
WriteConfiguration
}
if [[ -z "${config[homeserver]}" ]]; then
Log error "Failed to logout. No homeserver is configured."
Prompt
@ -34,13 +17,33 @@ MatrixLogout() {
Prompt
fi
# copy api map to local map
local -A api
CopyArray m_logout_api api
# input
local input_logout_confirm
Read -r -p "$(echo -e -n '\nYour local session will be erased and your access token will be invalidated. Logout anyway? (Y/n)')" input_logout_confirm
case "$input_logout_confirm" in
[yY]|[Yy][Ee][Ss] ) echo "Logging out...";;
[Nn]|[Nn][Oo] ) Prompt;;
esac
ReadConfiguration
DefineMatrixEndpoints
DoLogout
# set request parameters
local -A params=(
[method]="${api[method]}"
[path]="${api[path]}"
)
# make request
local response
Request params response || {
HandleMatrixError response
return 1
}
# remove user and session configuration
config[admin_user]=""
config[admin_token]=""
config[device_id]=""
WriteConfiguration
}

View File

@ -1,4 +1,4 @@
# Copyright (C) 2022 joe <joe@thisisjoes.site>
# Copyright (C) 2022-2023 joe <joe@thisisjoes.site>
# SPDX-License-Identifier: GPL-3.0-only
MatrixResolveAlias() {
@ -14,36 +14,43 @@ MatrixResolveAlias() {