Skip to content

Commit 5a1aacb

Browse files
delcin-rajyukibtc
authored andcommitted
mls: changed args of NostrMls::create_group and add new fields for NostrGroupDataExtension
- Add image url and key field for `NostrGroupDataExtension` - Changed `create_group` with `NostrGroupConfigData` - Adds ability to include group image in `NostrGroupDataExtension` - Alters existing `groups` and `welcomes` table to store the image url and key Pull-Request: #965 Signed-off-by: Yuki Kishimoto <[email protected]>
1 parent 684c695 commit 5a1aacb

File tree

20 files changed

+353
-81
lines changed

20 files changed

+353
-81
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mls/nostr-mls-memory-storage/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ nostr-mls-storage.workspace = true
1818
openmls = { git = "https://github.com/openmls/openmls", rev = "4cc0f594b11262083ad9827b3b2033052c6ef99f", default-features = false }
1919
openmls_memory_storage = { git = "https://github.com/openmls/openmls", rev = "4cc0f594b11262083ad9827b3b2033052c6ef99f", default-features = false }
2020
parking_lot = "0.12"
21+
22+
[dev-dependencies]
23+
aes-gcm = "0.10.3"

mls/nostr-mls-memory-storage/src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ impl NostrMlsStorageProvider for NostrMlsMemoryStorage {
171171
mod tests {
172172
use std::collections::BTreeSet;
173173

174+
use aes_gcm::aead::OsRng;
175+
use aes_gcm::{Aes128Gcm, KeyInit};
174176
use nostr::{EventId, Kind, PublicKey, RelayUrl, Tags, Timestamp, UnsignedEvent};
175177
use nostr_mls_storage::groups::types::{Group, GroupExporterSecret, GroupState, GroupType};
176178
use nostr_mls_storage::groups::GroupStorage;
@@ -183,6 +185,10 @@ mod tests {
183185

184186
use super::*;
185187

188+
pub fn generate_encryption_key() -> Vec<u8> {
189+
Aes128Gcm::generate_key(OsRng).to_vec()
190+
}
191+
186192
fn create_test_group_id() -> GroupId {
187193
GroupId::from_slice(&[1, 2, 3, 4])
188194
}
@@ -242,6 +248,8 @@ mod tests {
242248
let nostr_storage = NostrMlsMemoryStorage::new(storage);
243249
let mls_group_id = create_test_group_id();
244250
let nostr_group_id = create_test_nostr_group_id();
251+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
252+
let image_key = Some(generate_encryption_key());
245253
let group = Group {
246254
mls_group_id: mls_group_id.clone(),
247255
nostr_group_id,
@@ -253,6 +261,8 @@ mod tests {
253261
group_type: GroupType::Group,
254262
epoch: 0,
255263
state: GroupState::Active,
264+
image_url,
265+
image_key,
256266
};
257267
nostr_storage.save_group(group.clone()).unwrap();
258268
let found_group = nostr_storage
@@ -279,6 +289,8 @@ mod tests {
279289
let nostr_storage = NostrMlsMemoryStorage::new(storage);
280290
let mls_group_id = create_test_group_id();
281291
let nostr_group_id = create_test_nostr_group_id();
292+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
293+
let image_key = Some(generate_encryption_key());
282294
let group = Group {
283295
mls_group_id: mls_group_id.clone(),
284296
nostr_group_id,
@@ -290,6 +302,8 @@ mod tests {
290302
group_type: GroupType::Group,
291303
epoch: 0,
292304
state: GroupState::Active,
305+
image_url,
306+
image_key,
293307
};
294308
nostr_storage.save_group(group.clone()).unwrap();
295309
let relay_url1 = RelayUrl::parse("wss://relay1.example.com").unwrap();
@@ -334,6 +348,8 @@ mod tests {
334348
let nostr_storage = NostrMlsMemoryStorage::new(storage);
335349
let mls_group_id = create_test_group_id();
336350
let nostr_group_id = create_test_nostr_group_id();
351+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
352+
let image_key = Some(generate_encryption_key());
337353
let group = Group {
338354
mls_group_id: mls_group_id.clone(),
339355
nostr_group_id,
@@ -345,6 +361,8 @@ mod tests {
345361
group_type: GroupType::Group,
346362
epoch: 0,
347363
state: GroupState::Active,
364+
image_url,
365+
image_key,
348366
};
349367
nostr_storage.save_group(group.clone()).unwrap();
350368
let group_exporter_secret_0 = GroupExporterSecret {
@@ -417,6 +435,8 @@ mod tests {
417435
nostr_group_id,
418436
group_name: "Test Welcome Group".to_string(),
419437
group_description: "A test welcome group".to_string(),
438+
group_image_key: None,
439+
group_image_url: None,
420440
group_admin_pubkeys: BTreeSet::from([pubkey]),
421441
group_relays: BTreeSet::from([RelayUrl::parse("wss://relay.example.com").unwrap()]),
422442
welcomer: pubkey,
@@ -475,6 +495,8 @@ mod tests {
475495
let nostr_storage = NostrMlsMemoryStorage::new(storage);
476496
let mls_group_id = create_test_group_id();
477497
let nostr_group_id = create_test_nostr_group_id();
498+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
499+
let image_key = Some(generate_encryption_key());
478500
let group = Group {
479501
mls_group_id: mls_group_id.clone(),
480502
nostr_group_id,
@@ -486,6 +508,8 @@ mod tests {
486508
group_type: GroupType::Group,
487509
epoch: 0,
488510
state: GroupState::Active,
511+
image_url,
512+
image_key,
489513
};
490514
nostr_storage.save_group(group.clone()).unwrap();
491515
let event_id = EventId::all_zeros();
@@ -568,6 +592,8 @@ mod tests {
568592
// Create a test group to verify the cache works
569593
let mls_group_id = create_test_group_id();
570594
let nostr_group_id = create_test_nostr_group_id();
595+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
596+
let image_key = Some(generate_encryption_key());
571597
let group = Group {
572598
mls_group_id: mls_group_id.clone(),
573599
nostr_group_id,
@@ -579,6 +605,8 @@ mod tests {
579605
group_type: GroupType::Group,
580606
epoch: 0,
581607
state: GroupState::Active,
608+
image_url,
609+
image_key,
582610
};
583611

584612
// Save the group
@@ -598,6 +626,8 @@ mod tests {
598626
// Create a test group to verify the default implementation works
599627
let mls_group_id = create_test_group_id();
600628
let nostr_group_id = create_test_nostr_group_id();
629+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
630+
let image_key = Some(generate_encryption_key());
601631
let group = Group {
602632
mls_group_id: mls_group_id.clone(),
603633
nostr_group_id,
@@ -609,6 +639,8 @@ mod tests {
609639
group_type: GroupType::Group,
610640
epoch: 0,
611641
state: GroupState::Active,
642+
image_url,
643+
image_key,
612644
};
613645

614646
// Save the group

mls/nostr-mls-sqlite-storage/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ serde_json.workspace = true
2323
tracing = { workspace = true, features = ["std"] }
2424

2525
[dev-dependencies]
26+
aes-gcm = "0.10.3"
2627
tempfile.workspace = true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- Add image_url and image_key to groups table
2+
ALTER TABLE groups ADD COLUMN image_url TEXT;
3+
ALTER TABLE groups ADD COLUMN image_key BLOB;
4+
5+
-- Add group_image_url and image_key to welcomes table
6+
ALTER TABLE welcomes ADD COLUMN group_image_url TEXT;
7+
ALTER TABLE welcomes ADD COLUMN group_image_key BLOB;

mls/nostr-mls-sqlite-storage/src/db.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ pub fn row_to_group(row: &Row) -> SqliteResult<Group> {
5050
let nostr_group_id: [u8; 32] = row.get("nostr_group_id")?;
5151
let name: String = row.get("name")?;
5252
let description: String = row.get("description")?;
53+
let image_url: Option<String> = row.get("image_url")?;
54+
let image_key: Option<Vec<u8>> = row.get("image_key")?;
5355

5456
// Parse admin pubkeys from JSON
5557
let admin_pubkeys_json: &str = row.get_ref("admin_pubkeys")?.as_str()?;
@@ -84,6 +86,8 @@ pub fn row_to_group(row: &Row) -> SqliteResult<Group> {
8486
group_type,
8587
epoch,
8688
state,
89+
image_url,
90+
image_key,
8791
})
8892
}
8993

@@ -205,6 +209,8 @@ pub fn row_to_welcome(row: &Row) -> SqliteResult<Welcome> {
205209
let nostr_group_id: [u8; 32] = row.get("nostr_group_id")?;
206210
let group_name: String = row.get("group_name")?;
207211
let group_description: String = row.get("group_description")?;
212+
let group_image_url: Option<String> = row.get("group_image_url")?;
213+
let group_image_key: Option<Vec<u8>> = row.get("group_image_key")?;
208214
let group_admin_pubkeys_json: &str = row.get_ref("group_admin_pubkeys")?.as_str()?;
209215
let group_relays_json: &str = row.get_ref("group_relays")?.as_str()?;
210216
let welcomer_blob: &[u8] = row.get_ref("welcomer")?.as_blob()?;
@@ -241,6 +247,8 @@ pub fn row_to_welcome(row: &Row) -> SqliteResult<Welcome> {
241247
nostr_group_id,
242248
group_name,
243249
group_description,
250+
group_image_url,
251+
group_image_key,
244252
group_admin_pubkeys,
245253
group_relays,
246254
welcomer,

mls/nostr-mls-sqlite-storage/src/groups.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,15 @@ impl GroupStorage for NostrMlsSqliteStorage {
8888
conn_guard
8989
.execute(
9090
"INSERT INTO groups
91-
(mls_group_id, nostr_group_id, name, description, admin_pubkeys, last_message_id,
91+
(mls_group_id, nostr_group_id, name, description, image_url, image_key, admin_pubkeys, last_message_id,
9292
last_message_at, group_type, epoch, state)
93-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
93+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
9494
ON CONFLICT(mls_group_id) DO UPDATE SET
9595
nostr_group_id = excluded.nostr_group_id,
9696
name = excluded.name,
9797
description = excluded.description,
98+
image_url = excluded.image_url,
99+
image_key = excluded.image_key,
98100
admin_pubkeys = excluded.admin_pubkeys,
99101
last_message_id = excluded.last_message_id,
100102
last_message_at = excluded.last_message_at,
@@ -106,6 +108,8 @@ impl GroupStorage for NostrMlsSqliteStorage {
106108
&group.nostr_group_id,
107109
&group.name,
108110
&group.description,
111+
&group.image_url,
112+
&group.image_key,
109113
&admin_pubkeys_json,
110114
last_message_id,
111115
&last_message_at,
@@ -270,11 +274,17 @@ impl GroupStorage for NostrMlsSqliteStorage {
270274

271275
#[cfg(test)]
272276
mod tests {
277+
use aes_gcm::aead::OsRng;
278+
use aes_gcm::{Aes128Gcm, KeyInit};
273279
use nostr::RelayUrl;
274280
use nostr_mls_storage::groups::types::{GroupState, GroupType};
275281

276282
use super::*;
277283

284+
pub fn generate_encryption_key() -> Vec<u8> {
285+
Aes128Gcm::generate_key(OsRng).to_vec()
286+
}
287+
278288
#[test]
279289
fn test_save_and_find_group() {
280290
let storage = NostrMlsSqliteStorage::new_in_memory().unwrap();
@@ -283,6 +293,8 @@ mod tests {
283293
let mls_group_id = GroupId::from_slice(&[1, 2, 3, 4]);
284294
let mut nostr_group_id = [0u8; 32];
285295
nostr_group_id[0..13].copy_from_slice(b"test_group_12");
296+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
297+
let image_key = Some(generate_encryption_key());
286298

287299
let group = Group {
288300
mls_group_id: mls_group_id.clone(),
@@ -295,6 +307,8 @@ mod tests {
295307
group_type: GroupType::Group,
296308
epoch: 0,
297309
state: GroupState::Active,
310+
image_url,
311+
image_key,
298312
};
299313

300314
// Save the group
@@ -340,6 +354,8 @@ mod tests {
340354
group_type: GroupType::Group,
341355
epoch: 0,
342356
state: GroupState::Active,
357+
image_url: None,
358+
image_key: None,
343359
};
344360

345361
// Save the group
@@ -386,6 +402,8 @@ mod tests {
386402
group_type: GroupType::Group,
387403
epoch: 0,
388404
state: GroupState::Active,
405+
image_url: None,
406+
image_key: None,
389407
};
390408

391409
// Save the group

mls/nostr-mls-sqlite-storage/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ mod tests {
301301
group_type: GroupType::Group,
302302
epoch: 0,
303303
state: GroupState::Active,
304+
image_url: None,
305+
image_key: None,
304306
};
305307

306308
// Save the group

mls/nostr-mls-sqlite-storage/src/messages.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ mod tests {
140140
group_type: GroupType::Group,
141141
epoch: 0,
142142
state: GroupState::Active,
143+
image_url: None,
144+
image_key: None,
143145
};
144146

145147
// Save the group

mls/nostr-mls-sqlite-storage/src/welcomes.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,18 @@ impl WelcomeStorage for NostrMlsSqliteStorage {
3434
conn_guard
3535
.execute(
3636
"INSERT OR REPLACE INTO welcomes
37-
(id, event, mls_group_id, nostr_group_id, group_name, group_description,
37+
(id, event, mls_group_id, nostr_group_id, group_name, group_description, group_image_url, group_image_key,
3838
group_admin_pubkeys, group_relays, welcomer, member_count, state, wrapper_event_id)
39-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
39+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
4040
params![
4141
welcome.id.as_bytes(),
4242
welcome.event.as_json(),
4343
welcome.mls_group_id.as_slice(),
4444
welcome.nostr_group_id,
4545
welcome.group_name,
4646
welcome.group_description,
47+
welcome.group_image_url,
48+
welcome.group_image_key,
4749
group_admin_pubkeys_json,
4850
group_relays_json,
4951
welcome.welcomer.as_bytes(),
@@ -143,6 +145,8 @@ impl WelcomeStorage for NostrMlsSqliteStorage {
143145
mod tests {
144146
use std::collections::BTreeSet;
145147

148+
use aes_gcm::aead::OsRng;
149+
use aes_gcm::{Aes128Gcm, KeyInit};
146150
use nostr::{EventId, Kind, PublicKey, RelayUrl, Timestamp, UnsignedEvent};
147151
use nostr_mls_storage::groups::types::{Group, GroupState, GroupType};
148152
use nostr_mls_storage::groups::GroupStorage;
@@ -151,6 +155,10 @@ mod tests {
151155

152156
use super::*;
153157

158+
pub fn generate_encryption_key() -> Vec<u8> {
159+
Aes128Gcm::generate_key(OsRng).to_vec()
160+
}
161+
154162
#[test]
155163
fn test_save_and_find_welcome() {
156164
let storage = NostrMlsSqliteStorage::new_in_memory().unwrap();
@@ -159,6 +167,8 @@ mod tests {
159167
let mls_group_id = GroupId::from_slice(&[1, 2, 3, 4]);
160168
let mut nostr_group_id = [0u8; 32];
161169
nostr_group_id[0..13].copy_from_slice(b"test_group_12");
170+
let image_url = Some("http://blossom_server:4531/fake_img.png".to_owned());
171+
let image_key = Some(generate_encryption_key());
162172

163173
let group = Group {
164174
mls_group_id: mls_group_id.clone(),
@@ -171,11 +181,13 @@ mod tests {
171181
group_type: GroupType::Group,
172182
epoch: 0,
173183
state: GroupState::Active,
184+
image_url: image_url.clone(),
185+
image_key: image_key.clone(),
174186
};
175187

176188
// Save the group
177189
let result = storage.save_group(group);
178-
assert!(result.is_ok());
190+
assert!(result.is_ok(), "{:?}", result);
179191

180192
// Create a test welcome
181193
let event_id =
@@ -204,6 +216,8 @@ mod tests {
204216
nostr_group_id: welcome_nostr_group_id,
205217
group_name: "Test Group".to_string(),
206218
group_description: "A test group".to_string(),
219+
group_image_url: image_url,
220+
group_image_key: image_key,
207221
group_admin_pubkeys: BTreeSet::from([pubkey]),
208222
group_relays: BTreeSet::from([RelayUrl::parse("wss://relay.example.com").unwrap()]),
209223
welcomer: pubkey,
@@ -214,7 +228,7 @@ mod tests {
214228

215229
// Save the welcome
216230
let result = storage.save_welcome(welcome.clone());
217-
assert!(result.is_ok());
231+
assert!(result.is_ok(), "{:?}", result);
218232

219233
// Find by event ID
220234
let found_welcome = storage

0 commit comments

Comments
 (0)