mod/notification-matrix: introduce $SetupMatrix{Authenticate,JoinRoom} for setup

Well, now that we have a JSON parser... Let's improve the user
experience a bit.
This commit is contained in:
Christian Hesse 2023-11-08 13:08:49 +01:00
parent 59f8f30389
commit 2d7efd8d6c
9 changed files with 120 additions and 45 deletions

Binary file not shown.

Binary file not shown.

View file

@ -21,8 +21,8 @@ Just install the module:
$ScriptInstallUpdate mod/notification-matrix;
Also install a Matrix client on at least one of your mobile and/or desktop
devices. As there is no privilege separation you should create a dedicated
notification account, in addition to your general user account.
devices. Create and setup an account there, we will reference that as
"*general account*" later.
Configuration
-------------
@ -35,58 +35,53 @@ reload the configuration.
> [`global-config`](../../global-config.rsc) (the one without `-overlay`) to
> your local `global-config-overlay` and modify it to your specific needs.
### Home server
The Matrix server is connected via encrypted https, and certificate
verification is applied. So make sure you have the certificate chain for
your server in device's certificate store.
> **Info**: The *matrix.org* server uses a Cloudflare certificate. You can
> install that with: `$CertificateAvailable "Cloudflare Inc ECC CA-3"`
### From other device
If you have setup your Matrix *notification account* before just reuse that.
Copy the relevant configuration to the device to be configured.
### Setup new account
As there is no privilege separation you should create a dedicated account
for use with these scripts, in addition to your *general account*.
We will reference that as "*notification account*" in the following steps.
#### Authenticate
Matrix user accounts are identified by a unique user id in the form of
`@localpart:domain`. The `domain` part is not necessarily your home server
address, you have to resolve it with the procedure described in the
[Matrix specification](https://spec.matrix.org/latest/client-server-api/#server-discovery).
`@localpart:domain`. Use that and your password to generate an access token
and write first part of the configuration:
Your best bet is to query the server at `domain` with the
[well-known uri](https://spec.matrix.org/latest/client-server-api/#well-known-uri).
For "*matrix.org*" this query is:
$SetupMatrixAuthenticate "@example:matrix.org" "v3ry-s3cr3t";
/tool/fetch "https://matrix.org/.well-known/matrix/client" output=user;
![authenticate](notification-matrix.d/01-authenticate.avif)
![home server](notification-matrix.d/01-home-server.avif)
#### Join Room
So the home server for "*matrix.org*" is "*matrix-client.matrix.org*".
Please strip the protocol ("*https://*") for `MatrixHomeServer` if given.
Every Matix chat is a room, so we have to create one. Do that with your
*general account*, this makes sure your *general account* is the room owner.
Then join the room and invite the *notification account* by its user id
"*@example:matrix.org*".
Look up the *room id* within the Matrix client, it should read like
"*!WUcxpSjKyxSGelouhA:matrix.org*" (starting with an exclamation mark and
ending with the domain).
### Access token
Finally make the *notification account* join into the room by accepting
the invite.
After discovering the correct home server an access token has to be created.
For this the login credentials (username and password) of the notification
account must be sent to the home server via
[client server api](https://matrix.org/docs/guides/client-server-api#login).
$SetupMatrixJoinRoom "!WUcxpSjKyxSGelouhA:matrix.org";
We use the home server discovered above, "*matrix-client.matrix.org*".
The user is "*example*" and password is "*v3ry-s3cr3t*".
![join room](notification-matrix.d/02-join-room.avif)
/tool/fetch "https://matrix-client.matrix.org/_matrix/client/r0/login" http-method=post http-data="{\"type\":\"m.login.password\", \"user\":\"example\", \"password\":\"v3ry-s3cr3t\"}" output=user;
![access token](notification-matrix.d/02-access-token.avif)
The server replied with a JSON object containing the `access_token`, use that
for `MatrixAccessToken`.
### Room
Every Matix chat is a room, so we have to create one. Do so with your general
user, this makes sure your general user is the room owner. Then join the room
and invite the notification user by its user id "*@example:matrix.org*". Look
up the room id within the Matrix client, it should read like
"*!WUcxpSjKyxSGelouhA:matrix.org*". Use that for `MatrixRoom`.
Finally join the notification user to the room by accepting the invite. Again,
this can be done with
[client server api](https://matrix.org/docs/guides/client-server-api#joining-a-room-via-an-invite).
Make sure to replace room id ("*!*" is escaped with "*%21*") and access token
with your data.
/tool/fetch "https://matrix-client.matrix.org/_matrix/client/r0/rooms/%21WUcxpSjKyxSGelouhA:matrix.org/join?access_token=yt_ZXdvcm0tdGVzdA_NNqUyvKHRhBLZmnzVVSK_0xu6yN" http-method=post http-data="" output=user;
![join room](notification-matrix.d/03-join-room.avif)
The settings have been appended to `global-config-overlay`. You may want to
edit to move it to an appropriate place.
Usage and invocation
--------------------

View file

@ -12,7 +12,7 @@
:local 0 "global-functions";
# expected configuration version
:global ExpectedConfigVersion 112;
:global ExpectedConfigVersion 113;
# global variables not to be changed by user
:global GlobalFunctionsReady false;

View file

@ -12,6 +12,8 @@
:global PurgeMatrixQueue;
:global SendMatrix;
:global SendMatrix2;
:global SetupMatrixAuthenticate;
:global SetupMatrixJoinRoom;
# flush Matrix queue
:set FlushMatrixQueue do={
@ -175,3 +177,80 @@
($NotificationFunctions->"matrix") ("\$NotificationFunctions->\"matrix\"") $Notification;
}
# setup - get home server and access token
:set SetupMatrixAuthenticate do={
:local User [ :tostr $1 ];
:local Pass [ :tostr $2 ];
:global CharacterReplace;
:global LogPrintExit2;
:global ParseJson;
:global UrlEncode;
:global MatrixAccessToken;
:global MatrixHomeServer;
:local Domain [ :pick $User ([ :find $User ":" ] + 1) [ :len $User] ];
:do {
:local Data ([ /tool/fetch check-certificate=yes-without-crl output=user \
("https://" . $Domain . "/.well-known/matrix/client") as-value ]->"data");
:set MatrixHomeServer ([ $ParseJson ([ $ParseJson [ $CharacterReplace $Data " " "" ] ]->"m.homeserver") ]->"base_url");
$LogPrintExit2 debug $0 ("Home server is: " . $MatrixHomeServer) false;
} on-error={
$LogPrintExit2 error $0 ("Failed getting home server!") true;
}
:if ([ :pick $MatrixHomeServer 0 8 ] = "https://") do={
:set MatrixHomeServer [ :pick $MatrixHomeServer 8 [ :len $MatrixHomeServer ] ];
}
:do {
:local Data ([ /tool/fetch check-certificate=yes-without-crl output=user \
http-method=post http-data=("{\"type\":\"m.login.password\", \"user\":\"" . $User . "\", \"password\":\"" . $Pass . "\"}") \
("https://" . $MatrixHomeServer . "/_matrix/client/r0/login") as-value ]->"data");
:set MatrixAccessToken ([ $ParseJson $Data ]->"access_token");
$LogPrintExit2 debug $0 ("Access token is: " . $MatrixAccessToken) false;
} on-error={
$LogPrintExit2 error $0 ("Failed logging in (and getting access token)!") true;
}
:do {
/system/script/set global-config-overlay source=([ get global-config-overlay source ] . "\n" . \
":global MatrixHomeServer \"" . $MatrixHomeServer . "\";\n" . \
":global MatrixAccessToken \"" . $MatrixAccessToken . "\";\n");
$LogPrintExit2 info $0 ("Appended configuration to global-config-overlay. Now create and join a room, please!") false;
} on-error={
$LogPrintExit2 error $0 ("Failed appending configuration to global-config-overlay!") true;
}
}
# setup - join a room
:set SetupMatrixJoinRoom do={
:global MatrixRoom [ :tostr $1 ];
:global LogPrintExit2;
:global UrlEncode;
:global MatrixAccessToken;
:global MatrixHomeServer;
:global MatrixRoom;
:do {
/tool/fetch check-certificate=yes-without-crl output=none \
http-method=post http-data="" \
("https://" . $MatrixHomeServer . "/_matrix/client/r0/rooms/" . [ $UrlEncode $MatrixRoom ] . \
"/join?access_token=" . [ $UrlEncode $MatrixAccessToken ]) as-value;
$LogPrintExit2 debug $0 ("Joined the room.") false;
} on-error={
$LogPrintExit2 error $0 ("Failed joining the room!") true;
}
:do {
/system/script/set global-config-overlay source=([ get global-config-overlay source ] . "\n" . \
":global MatrixRoom \"" . $MatrixRoom . "\";\n");
$LogPrintExit2 info $0 ("Appended configuration to global-config-overlay. Please review and cleanup!") false;
} on-error={
$LogPrintExit2 error $0 ("Failed appending configuration to global-config-overlay!") true;
}
}

View file

@ -26,6 +26,7 @@
110="Dropped support for loading scripts from local storage.";
111="Modified 'dhcp-to-dns' to allow multiple records for one mac address.";
112="Enhanced 'mod/ssh-keys-import' to record the fingerprint of keys.";
113="Added helper functions for easier setup to Matrix notification module.";
};
# Migration steps to be applied on script updates