Skip to content

Commit 6550586

Browse files
committed
Add SynapseReader support for devices
1 parent 4354f61 commit 6550586

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 {
@@ -386,6 +397,22 @@ impl<'conn> SynapseReader<'conn> {
386397
.map_err(|err| err.into_database("reading Synapse user external IDs"))
387398
}
388399

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

445472
use crate::{
446473
synapse_reader::{
447-
SynapseAccessToken, SynapseExternalId, SynapseRefreshToken, SynapseThreepid,
448-
SynapseUser,
474+
SynapseAccessToken, SynapseDevice, SynapseExternalId, SynapseRefreshToken,
475+
SynapseThreepid, SynapseUser,
449476
},
450477
SynapseReader,
451478
};
@@ -501,6 +528,22 @@ mod test {
501528
assert_debug_snapshot!(external_ids);
502529
}
503530

531+
#[sqlx::test(migrator = "MIGRATOR", fixtures("user_alice", "devices_alice"))]
532+
async fn test_read_devices(pool: PgPool) {
533+
let mut conn = pool.acquire().await.expect("failed to get connection");
534+
let mut reader = SynapseReader::new(&mut conn, false)
535+
.await
536+
.expect("failed to make SynapseReader");
537+
538+
let devices: BTreeSet<SynapseDevice> = reader
539+
.read_devices()
540+
.try_collect()
541+
.await
542+
.expect("failed to read Synapse devices");
543+
544+
assert_debug_snapshot!(devices);
545+
}
546+
504547
#[sqlx::test(migrator = "MIGRATOR", fixtures("user_alice", "access_token_alice"))]
505548
async fn test_read_access_token(pool: PgPool) {
506549
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)