ma1uta / ma1sd

Federated Matrix Identity Server (formerly fork of kamax/mxisd)
GNU Affero General Public License v3.0
167 stars 56 forks source link

Feature: Add possibility to search user_directory of another homeserver #52

Open rda0 opened 4 years ago

rda0 commented 4 years ago

I have a synapse homserver my.homeserver with ma1sd that uses our own small LDAP server as a backend. At our university we have another federated homeserver (other.homeserver) without ma1sd. I would like to include the user_directory of other.homeserver in the search results. It could be done using the EXEC backend, as follows.

Configuration snippet /etc/ma1sd/ma1sd.yaml

exec:
  directory:
    enabled: true
    search:
      byName:
        command: '/opt/ma1sd-exec/other.homserver/user-directory.py'
        args: ['{query}']
        output:
          type: 'json'

EXEC script /opt/ma1sd-exec/other.homserver/user-directory.py:

#!/usr/bin/env python3

import argparse
import requests
import json

from secret import access_token

parser = argparse.ArgumentParser()
parser.add_argument("term", help="search term")
args = parser.parse_args()

data = {'search_term': args.term}
json_data = json.dumps(data)

response = requests.post(
    'https://other.homserver/_matrix/client/r0/user_directory/search',
    headers={'Authorization': ' '.join(['Bearer', access_token])},
    data=json_data)

json_response = response.json()
json_filtered = {'limited': json_response['limited'], 'results': []}

for user in json_response['results']:
    if user['user_id'].endswith(':other.homserver'):
        json_filtered['results'].append(user)

print(json.dumps(json_filtered, indent=4, sort_keys=True))

The script queries https://other.homserver/_matrix/client/r0/user_directory/search and filters the results:

$ /opt/ma1sd-exec/other.homserver/user-directory.py user
{
    "limited": false,
    "results": [
        {
            "avatar_url": null,
            "display_name": "User",
            "user_id": "@user:other.homserver"
        }
    ]
}

Since the backend expects the localpart of the user_id and always appends the my.homeserver domain, ma1sd returns the following mxid in the search results:

@@user:other.homserver:my.homeserver

It would be great to have a configuration option to allow raw mxid output from exec scripts.

I currently made the following patch to 2.4.0, which works for our use case:

diff --git a/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java b/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java
index 5bf4d2e..9b75533 100644
--- a/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java
+++ b/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java
@@ -20,6 +20,8 @@

 package io.kamax.mxisd.backend.exec;

+import java.util.regex.Matcher;
+
 import io.kamax.matrix.MatrixID;
 import io.kamax.matrix.json.GsonUtil;
 import io.kamax.mxisd.config.ExecConfig;
@@ -65,7 +67,12 @@ public class ExecDirectoryStore extends ExecStore implements DirectoryProvider {

             UserDirectorySearchResult response = GsonUtil.get().fromJson(output, UserDirectorySearchResult.class);
             for (UserDirectorySearchResult.Result result : response.getResults()) {
-                result.setUserId(MatrixID.asAcceptable(result.getUserId(), mxCfg.getDomain()).getId());
+                Matcher m = MatrixID.LAX_PATTERN.matcher(result.getUserId());
+                if (m.matches()) {
+                    result.setUserId(MatrixID.asAcceptable(result.getUserId()).getId());
+                } else {
+                    result.setUserId(MatrixID.asAcceptable(result.getUserId(), mxCfg.getDomain()).getId());
+                }
             }
             return response;
         });