Skip to content

Commit 9863c88

Browse files
reivilibresandhose
authored andcommitted
Add SynapseReader support for devices
1 parent 62c21e4 commit 9863c88

File tree

4 files changed

+124
-2
lines changed

4 files changed

+124
-2
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
INSERT INTO devices
2+
(
3+
user_id,
4+
device_id,
5+
display_name,
6+
last_seen,
7+
ip,
8+
user_agent,
9+
hidden
10+
)
11+
VALUES
12+
(
13+
'@alice:example.com',
14+
'ADEVICE',
15+
'Matrix Console',
16+
1623366000000,
17+
'203.0.113.1',
18+
'Browser/5.0 (X12; ComputerOS 64; rv:1024.0)',
19+
FALSE
20+
),
21+
(
22+
'@alice:example.com',
23+
'master signing key',
24+
NULL,
25+
NULL,
26+
NULL,
27+
NULL,
28+
TRUE
29+
),
30+
(
31+
'@alice:example.com',
32+
'self_signing signing key',
33+
NULL,
34+
NULL,
35+
NULL,
36+
NULL,
37+
TRUE
38+
);

crates/syn2mas/src/synapse_reader/mod.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ pub struct SynapseExternalId {
209209
pub external_id: String,
210210
}
211211

212+
/// Row of the `devices` table in Synapse.
213+
#[derive(Clone, Debug, FromRow, PartialEq, Eq, PartialOrd, Ord)]
214+
pub struct SynapseDevice {
215+
pub user_id: FullUserId,
216+
pub device_id: String,
217+
pub display_name: Option<String>,
218+
pub last_seen: Option<MillisecondsTimestamp>,
219+
pub ip: Option<String>,
220+
pub user_agent: Option<String>,
221+
}
222+
212223
/// Row of the `access_tokens` table in Synapse.
213224
#[derive(Clone, Debug, FromRow, PartialEq, Eq, PartialOrd, Ord)]
214225
pub struct SynapseAccessToken {
@@ -387,6 +398,22 @@ impl<'conn> SynapseReader<'conn> {
387398
.map_err(|err| err.into_database("reading Synapse user external IDs"))
388399
}
389400

401+
/// Reads devices from the Synapse database.
402+
/// Does not include so-called 'hidden' devices, which are just a mechanism
403+
/// for storing various signing keys shared between the real devices.
404+
pub fn read_devices(&mut self) -> impl Stream<Item = Result<SynapseDevice, Error>> + '_ {
405+
sqlx::query_as(
406+
"
407+
SELECT
408+
user_id, device_id, display_name, last_seen, ip, user_agent
409+
FROM devices
410+
WHERE NOT hidden
411+
",
412+
)
413+
.fetch(&mut *self.txn)
414+
.map_err(|err| err.into_database("reading Synapse devices"))
415+
}
416+
390417
/// Reads access tokens from the Synapse database.
391418
/// This does not include access tokens used for puppetting users, as those
392419
/// are not supported by MAS. This also does not include access tokens
@@ -446,8 +473,8 @@ mod test {
446473

447474
use crate::{
448475
synapse_reader::{
449-
SynapseAccessToken, SynapseExternalId, SynapseRefreshToken, SynapseThreepid,
450-
SynapseUser,
476+
SynapseAccessToken, SynapseDevice, SynapseExternalId, SynapseRefreshToken,
477+
SynapseThreepid, SynapseUser,
451478
},
452479
SynapseReader,
453480
};
@@ -503,6 +530,22 @@ mod test {
503530
assert_debug_snapshot!(external_ids);
504531
}
505532

533+
#[sqlx::test(migrator = "MIGRATOR", fixtures("user_alice", "devices_alice"))]
534+
async fn test_read_devices(pool: PgPool) {
535+
let mut conn = pool.acquire().await.expect("failed to get connection");
536+
let mut reader = SynapseReader::new(&mut conn, false)
537+
.await
538+
.expect("failed to make SynapseReader");
539+
540+
let devices: BTreeSet<SynapseDevice> = reader
541+
.read_devices()
542+
.try_collect()
543+
.await
544+
.expect("failed to read Synapse devices");
545+
546+
assert_debug_snapshot!(devices);
547+
}
548+
506549
#[sqlx::test(migrator = "MIGRATOR", fixtures("user_alice", "access_token_alice"))]
507550
async fn test_read_access_token(pool: PgPool) {
508551
let mut conn = pool.acquire().await.expect("failed to get connection");
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
source: crates/syn2mas/src/synapse_reader/mod.rs
3+
expression: devices
4+
---
5+
{
6+
SynapseDevice {
7+
user_id: FullUserId(
8+
"@alice:example.com",
9+
),
10+
device_id: "ADEVICE",
11+
display_name: Some(
12+
"Matrix Console",
13+
),
14+
last_seen: Some(
15+
MillisecondsTimestamp(
16+
2021-06-10T23:00:00Z,
17+
),
18+
),
19+
ip: Some(
20+
"203.0.113.1",
21+
),
22+
user_agent: Some(
23+
"Browser/5.0 (X12; ComputerOS 64; rv:1024.0)",
24+
),
25+
},
26+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- Copyright 2025 New Vector Ltd.
2+
--
3+
-- SPDX-License-Identifier: AGPL-3.0-only
4+
-- Please see LICENSE in the repository root for full details.
5+
6+
-- Brings in the `devices` table from Synapse
7+
CREATE TABLE devices (
8+
user_id text NOT NULL,
9+
device_id text NOT NULL,
10+
display_name text,
11+
last_seen bigint,
12+
ip text,
13+
user_agent text,
14+
hidden boolean DEFAULT false
15+
);

0 commit comments

Comments
 (0)