Skip to content

Commit 630c079

Browse files
committed
feat: add set-matrix-server action
1 parent bf7bd22 commit 630c079

File tree

5 files changed

+108
-72
lines changed

5 files changed

+108
-72
lines changed

README.md

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,40 +67,21 @@ Consumers of the events must then run the `get-phonebook-credentials` action on
6767

6868
## Matrix integration
6969

70-
This module provides optional integration with a Matrix server module (for example `matrix5`). Integration is implemented so the Matrix module can call into FreePBX to authenticate or validate users.
70+
Provides optional integration with a Matrix server module (e.g. `matrix5`). Use the included helper action `set-matrix-server` to enable or disable the NethVoice authentication endpoint on a Matrix instance.
7171

72-
A helper action `set-matrix-server` was added to manage this integration. The action performs the following steps:
72+
The action sets or clears the `nethvoice_auth_url` used by the Matrix module to call FreePBX for external authentication.
7373

74-
- Resolve the target Matrix module using the module UUID stored in Redis under `module/<module_id>/environment` as the `MODULE_UUID` field. The action only uses this method for resolution and will fail if the UUID is not found.
75-
- Calls `get-configuration` on the local NethVoice module to obtain `nethvoice_host`.
76-
- Calls `get-configuration` on the target Matrix module to obtain its current configuration.
77-
- Sets the `nethvoice_auth_url` field to either `https://<nethvoice_host>/freepbx/rest/testextauth` when integration is enabled, or to the empty string when disabled.
78-
- Calls `configure-module` on the Matrix module with the merged configuration (the Matrix module's existing `get-configuration` response with `nethvoice_auth_url` overridden).
74+
Parameters:
75+
- `module_uuid`: string, required - the UUID of the Matrix module instance to update, find it using ` redis-cli hget module/matrix1/environment MODULE_UUID`
76+
- `enable_integration`: boolean, required
7977

80-
This approach ensures the Matrix module receives a full, consistent payload suitable for its `configure-module` handler while only changing the authentication endpoint field required for NethVoice integration.
81-
82-
### Action: `set-matrix-server`
83-
84-
- Location: `imageroot/actions/set-matrix-server/10setenvs`
85-
- Input schema: `imageroot/actions/set-matrix-server/validate-input.json`
86-
- Parameters:
87-
- `module_uuid` (string, required): the UUID of the Matrix module instance to configure. The action will locate the module id by scanning `module/*/environment` for the `MODULE_UUID` value.
88-
- `enable_integration` (boolean, required): `true` to enable integration (sets the `nethvoice_auth_url`), `false` to disable it (clears the field).
89-
90-
### Example usage
91-
92-
Run the action as a cluster task (example JSON payload):
78+
Example payload:
9379

9480
```
95-
{
96-
"module_uuid": "cf50b191-95d5-435b-bf34-0905bf7dba55",
97-
"enable_integration": true
98-
}
81+
{ "module_uuid": "cf50b191-95d5-435b-bf34-0905bf7dba55", "enable_integration": true }
9982
```
10083

101-
The action will find the module id (for example `matrix5`) by scanning Redis, fetch both configurations, set `nethvoice_auth_url` to `https://<nethvoice_host>/freepbx/rest/testextauth` and call `configure-module` on the `module/matrix5` agent.
102-
103-
If you prefer to run this manually for testing, use the `agent.tasks.run` equivalent on the cluster admin node or invoke the module task from your management tooling.
84+
When enabling integration the `nethvoice_auth_url` is set to `https://<nethvoice_host>/freepbx/rest/testextauth` (using the configured NethVoice host); disabling the integration clears the field.
10485

10586

10687
## Uninstall

imageroot/actions/restore-module/20copyenv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ restore_envs = [
113113
'TIMEZONE',
114114
'TRAEFIK_HTTP2HTTPS',
115115
'USER_DOMAIN',
116+
'NETHVOICE_MATRIX_UUID'
116117
]
117118

118119
for env in restore_envs:
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python3
2+
3+
#
4+
# Copyright (C) 2025 Nethesis S.r.l.
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
#
7+
8+
import sys
9+
import os
10+
import agent
11+
12+
def resolve_module_id_from_uuid(uuid):
13+
# Redis stores module info under module/{id}/uuid -> value
14+
# We need to search for the module id that has this uuid
15+
with agent.redis_connect() as rdb:
16+
# Only method: check environment hashes where MODULE_UUID is stored (user-provided format)
17+
for key in rdb.scan_iter(match='module/*/environment'):
18+
try:
19+
k = key.decode() if isinstance(key, bytes) else key
20+
module_uuid_val = rdb.hget(k, 'MODULE_UUID')
21+
if module_uuid_val and module_uuid_val.decode() == uuid:
22+
parts = k.split('/')
23+
if len(parts) >= 2:
24+
return parts[1]
25+
except Exception:
26+
continue
27+
return None
28+
29+
def get_configuration(module_id):
30+
matrix_agent_id = f'module/{module_id}'
31+
response = agent.tasks.run(agent_id=matrix_agent_id, action='get-configuration', data={})
32+
agent.assert_exp(response['exit_code'] == 0)
33+
return response
34+
35+
def set_configuration(module_id, config):
36+
matrix_agent_id = f'module/{module_id}'
37+
response = agent.tasks.run(agent_id=matrix_agent_id, action='configure-module', data=config)
38+
agent.assert_exp(response['exit_code'] == 0)
39+
return response
40+
41+
module_uuid = os.getenv('NETHVOICE_MATRIX_UUID', '')
42+
if module_uuid == '':
43+
# No matrix integration to restore
44+
sys.exit(0)
45+
46+
# Resolve module uuid to module id
47+
module_id = resolve_module_id_from_uuid(module_uuid)
48+
if module_id is None:
49+
# Matrix not found, nothing to restore
50+
print(agent.SD_WARNING + f"Module UUID {module_uuid} not found: cannot restore Matrix integration")
51+
sys.exit(0)
52+
53+
config = get_configuration(module_id)
54+
nethvoice_host = os.environ.get('NETHVOICE_HOST', '')
55+
if nethvoice_host:
56+
config['nethvoice_auth_url'] = f'https://{nethvoice_host}/freepbx/rest/testextauth'
57+
set_configuration(module_id, config)
58+
else:
59+
print(agent.SD_WARNING + "NETHVOICE_HOST not set: cannot restore Matrix integration")

imageroot/actions/set-matrix-server/10setenvs

100644100755
Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import json
99
import sys
1010
import os
11-
1211
import agent
1312

1413
request = json.load(sys.stdin)
@@ -30,44 +29,44 @@ def resolve_module_id_from_uuid(uuid):
3029
continue
3130
return None
3231

32+
def get_configuration(module_id):
33+
matrix_agent_id = f'module/{module_id}'
34+
response = agent.tasks.run(agent_id=matrix_agent_id, action='get-configuration', data={})
35+
agent.assert_exp(response['exit_code'] == 0)
36+
return response
3337

34-
module_uuid = request.get('module_uuid')
35-
enable_integration = request.get('enable_integration', False)
36-
37-
if not module_uuid:
38-
print(json.dumps({'exit_code': 2, 'message': 'module_uuid is required'}))
39-
sys.exit(2)
40-
41-
# Resolve module uuid to module id
42-
module_id = resolve_module_id_from_uuid(module_uuid)
43-
if module_id is None:
44-
print(json.dumps({'exit_code': 2, 'message': f'module_uuid {module_uuid} not found via module/*/environment'}))
45-
sys.exit(2)
46-
47-
# Build agent id for module
48-
matrix_agent_id = f'module/{module_id}'
49-
50-
# Call get-configuration on current nethvoice module to obtain hostname
51-
response = agent.tasks.run(agent_id=os.environ['AGENT_ID'], action='get-configuration', data={})
52-
agent.assert_exp(response['exit_code'] == 0)
38+
def set_configuration(module_id, config):
39+
matrix_agent_id = f'module/{module_id}'
40+
response = agent.tasks.run(agent_id=matrix_agent_id, action='configure-module', data=config)
41+
agent.assert_exp(response['exit_code'] == 0)
42+
return response
5343

54-
nconfig = response.get('result', {})
55-
nethvoice_host = nconfig.get('nethvoice_host', os.environ.get('NETHVOICE_HOST', ''))
56-
57-
# Call get-configuration on the matrix module and use its response for configure-module
58-
response = agent.tasks.run(agent_id=matrix_agent_id, action='get-configuration', data={})
59-
agent.assert_exp(response['exit_code'] == 0)
60-
61-
matrix_config = response.get('result', {}) or {}
62-
63-
if enable_integration:
64-
nethvoice_auth_url = f'https://{nethvoice_host}/freepbx/rest/testextauth' if nethvoice_host else '/freepbx/rest/testextauth'
65-
else:
66-
nethvoice_auth_url = ''
67-
68-
# Merge/override nethvoice_auth_url into matrix configuration
69-
matrix_config['nethvoice_auth_url'] = nethvoice_auth_url
70-
71-
# Call configure-module on matrix module with merged configuration
72-
response = agent.tasks.run(agent_id=matrix_agent_id, action='configure-module', data=matrix_config)
73-
agent.assert_exp(response['exit_code'] == 0)
44+
module_uuid = request.get('module_uuid')
45+
current_module_uuid = os.getenv('NETHVOICE_MATRIX_UUID', '')
46+
47+
if current_module_uuid == module_uuid:
48+
# No change, nothing to do
49+
sys.exit(0)
50+
51+
if current_module_uuid != '' and module_uuid == '':
52+
# Disable integration on old module
53+
module_id = resolve_module_id_from_uuid(current_module_uuid)
54+
if module_id is not None:
55+
config = get_configuration(module_id)
56+
config['nethvoice_auth_url'] = ''
57+
set_configuration(module_id, config)
58+
else:
59+
print(agent.SD_WARNING + f"Module UUID {current_module_uuid} not found: cannot disable Matrix integration")
60+
if current_module_uuid == '' and module_uuid != '':
61+
# Enable integration on new module
62+
module_id = resolve_module_id_from_uuid(module_uuid)
63+
if module_id is not None:
64+
nethvoice_host = os.environ.get('NETHVOICE_HOST', '')
65+
if nethvoice_host:
66+
config = get_configuration(module_id)
67+
config['nethvoice_auth_url'] = f'https://{nethvoice_host}/freepbx/rest/testextaut'
68+
set_configuration(module_id, config)
69+
else:
70+
print(agent.SD_WARNING + "NETHVOICE_HOST is not set, cannot enable Matrix integration")
71+
else:
72+
print(agent.SD_WARNING + f"Module UUID {module_uuid} not found: cannot enable Matrix integration")

imageroot/actions/set-matrix-server/validate-input.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@
44
"$id": "http://nethserver.org/json-schema/task/input/nethvoice/set-matrix-server",
55
"description": "Enable or disable NethVoice integration on Matrix server",
66
"type": "object",
7-
"required": ["module_uuid", "enable_integration"],
7+
"required": ["module_uuid"],
88
"properties": {
99
"module_uuid": {
1010
"description": "Module UUID of the Matrix module to configure",
1111
"type": "string"
12-
},
13-
"enable_integration": {
14-
"description": "Enable integration with NethVoice",
15-
"type": "boolean"
1612
}
1713
}
1814
}

0 commit comments

Comments
 (0)