1{
2 lib,
3 ...
4}:
5
6{
7 name = "draupnir";
8 meta.maintainers = with lib.maintainers; [
9 RorySys
10 emilylange
11 ];
12
13 nodes = {
14 homeserver =
15 { pkgs, ... }:
16 {
17 services.matrix-synapse = {
18 enable = true;
19 log.root.level = "WARNING";
20 settings = {
21 database.name = "sqlite3";
22 registration_shared_secret = "supersecret-registration";
23
24 listeners = [
25 {
26 bind_addresses = [
27 "::"
28 ];
29 port = 8008;
30 resources = [
31 {
32 compress = true;
33 names = [ "client" ];
34 }
35 {
36 compress = false;
37 names = [ "federation" ];
38 }
39 ];
40 tls = false;
41 type = "http";
42 x_forwarded = false;
43 }
44 ];
45 };
46 };
47
48 specialisation.draupnir = {
49 inheritParentConfig = true;
50
51 configuration.services.draupnir = {
52 enable = true;
53 settings = {
54 homeserverUrl = "http://localhost:8008";
55 managementRoom = "#moderators:homeserver";
56 };
57 secrets = {
58 accessToken = "/tmp/draupnir-access-token";
59 };
60 };
61 };
62
63 environment.systemPackages = with pkgs; [
64 curl
65 jq
66 (writers.writePython3Bin "test_draupnir_in_matrix"
67 {
68 libraries = [ python3Packages.matrix-nio ];
69 flakeIgnore = [ "E501" ];
70 }
71 ''
72 import asyncio
73 from nio import AsyncClient, MatrixRoom, RoomMemberEvent, RoomMessageNotice
74
75
76 async def main() -> None:
77 client = AsyncClient("http://localhost:8008", "moderator")
78
79 async def member_callback(room: MatrixRoom, event: RoomMemberEvent) -> None:
80 if event.membership == "join" and event.sender == "@draupnir:homeserver":
81 await client.room_send(
82 room_id=room.room_id,
83 message_type="m.room.message",
84 content={
85 "msgtype": "m.text",
86 "body": "!draupnir status"
87 }
88 )
89
90 async def message_callback(room: MatrixRoom, event: RoomMessageNotice) -> None:
91 print(f"{event.sender}: {event.body}")
92 if event.sender == "@draupnir:homeserver":
93 await client.close()
94 exit(0)
95
96 client.add_event_callback(member_callback, RoomMemberEvent)
97 client.add_event_callback(message_callback, RoomMessageNotice)
98
99 print(await client.login("password"))
100
101 room = await client.room_create(
102 name="Moderators",
103 alias="moderators",
104 invite=["@draupnir:homeserver"],
105 power_level_override={
106 "users": {
107 "@draupnir:homeserver": 100,
108 "@moderator:homeserver": 100,
109 }
110 }
111 )
112 print(room)
113
114 print(await client.join(room.room_id))
115
116 await client.sync_forever(timeout=30000)
117
118
119 asyncio.run(main())
120 ''
121 )
122 ];
123 };
124 };
125
126 testScript =
127 { nodes, ... }:
128 ''
129 import json
130
131 homeserver.wait_for_unit("matrix-synapse.service")
132 homeserver.wait_until_succeeds("curl --fail -L http://localhost:8008/")
133
134 homeserver.succeed("matrix-synapse-register_new_matrix_user -u draupnir -p password --no-admin")
135 homeserver.succeed("matrix-synapse-register_new_matrix_user -u moderator -p password --no-admin")
136
137 # get draupnir access token
138 payload = json.dumps({ "type": "m.login.password", "user": "draupnir", "password": "password" })
139 homeserver.succeed(
140 f"curl --fail --json '{payload}' http://localhost:8008/_matrix/client/v3/login"
141 + " | jq -r .access_token"
142 + " | tee /tmp/draupnir-access-token"
143 )
144
145 homeserver.succeed("${nodes.homeserver.system.build.toplevel}/specialisation/draupnir/bin/switch-to-configuration test")
146 homeserver.wait_for_unit("draupnir.service")
147
148 print(homeserver.succeed("test_draupnir_in_matrix >&2", timeout=60))
149 '';
150}