From a5bcf1a35691f54a098dc0860f584c4d528d3d40 Mon Sep 17 00:00:00 2001
From: Bob Mottram <bob@freedombone.net>
Date: Wed, 5 Aug 2020 13:05:39 +0100
Subject: [PATCH] Devices endpoint

---
 daemon.py  | 19 +++++++++++++++++++
 devices.py | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 devices.py

diff --git a/daemon.py b/daemon.py
index cf92a69e9..a02577f4c 100644
--- a/daemon.py
+++ b/daemon.py
@@ -192,6 +192,7 @@ from bookmarks import undoBookmark
 from petnames import setPetName
 from followingCalendar import addPersonToCalendar
 from followingCalendar import removePersonFromCalendar
+from devices import devicesCollection
 import os
 
 
@@ -1536,6 +1537,24 @@ class PubServer(BaseHTTPRequestHandler):
                 self._404()
                 return
 
+        # list of registered devices for e2ee
+        # see https://github.com/tootsuite/mastodon/pull/13820
+        if not htmlGET and authorized and '/users/' in self.path:
+            if self.path.endswith('/collections/devices'):
+                nickname = self.path.split('/users/')
+                if '/' in nickname:
+                    nickname = nickname.split('/')[0]
+                devJson = devicesCollection(self.server.baseDir,
+                                            nickname, self.server.domain,
+                                            self.server.domainFull,
+                                            self.server.httpPrefix)
+                msg = json.dumps(devJson,
+                                 ensure_ascii=False).encode('utf-8')
+                self._set_headers('application/json',
+                                  len(msg),
+                                  None, callingDomain)
+                self._write(msg)
+
         if htmlGET and '/users/' in self.path:
             # show the person options screen with view/follow/block/report
             if '?options=' in self.path:
diff --git a/devices.py b/devices.py
new file mode 100644
index 000000000..607b6ee36
--- /dev/null
+++ b/devices.py
@@ -0,0 +1,39 @@
+__filename__ = "devices.py"
+__author__ = "Bob Mottram"
+__license__ = "AGPL3+"
+__version__ = "1.1.0"
+__maintainer__ = "Bob Mottram"
+__email__ = "bob@freedombone.net"
+__status__ = "Production"
+
+import os
+from utils import loadJson
+
+
+def devicesCollection(baseDir: str, nickname: str, domain: str,
+                      domainFull: str, httpPrefix: str) -> {}:
+    """Returns a list of registered devices
+    """
+    personDir = baseDir + '/accounts/' + nickname + '@' + domain
+    if not os.path.isdir(personDir):
+        return {}
+    personId = httpPrefix + '://' + domainFull + '/users/' + nickname
+    if not os.path.isdir(personDir + '/devices'):
+        os.mkdir(personDir + '/devices')
+    deviceList = []
+    for subdir, dirs, files in os.walk(personDir + '/devices/'):
+        for dev in files:
+            if not dev.endswith('.json'):
+                continue
+            deviceFilename = os.path.join(personDir + '/devices', dev)
+            devJson = loadJson(deviceFilename)
+            if devJson:
+                deviceList.append(devJson)
+
+    devicesDict = {
+        'id': personId + '/collections/devices',
+        'type': 'Collection',
+        'totalItems': len(deviceList),
+        'items': deviceList
+    }
+    return devicesDict