Compare commits

...

2 Commits

Author SHA1 Message Date
Hocuri
35961a0a33 Add two TODOs, and remove two 2026-03-16 15:00:08 +01:00
Hocuri
57529407e3 Make things work. Next: Tests, make sure that primary transport is published 2026-03-16 14:41:35 +01:00
7 changed files with 89 additions and 29 deletions

View File

@@ -6784,8 +6784,8 @@ void dc_event_unref(dc_event_t* event);
* UI should update the list.
*
* The event is emitted when the transports are modified on another device
* using the JSON-RPC calls `add_or_update_transport`, `add_transport_from_qr`, `delete_transport`
* or `set_config(configured_addr)`.
* using the JSON-RPC calls `add_or_update_transport`, `add_transport_from_qr`, `delete_transport`,
* `set_transport_unpublished` or `set_config(configured_addr)`.
*/
#define DC_EVENT_TRANSPORTS_MODIFIED 2600

View File

@@ -528,6 +528,7 @@ impl CommandApi {
/// from a server encoded in a QR code.
/// - [Self::list_transports()] to get a list of all configured transports.
/// - [Self::delete_transport()] to remove a transport.
/// - [Self::set_transport_unpublished()] to set whether contacts see this transport.
async fn add_or_update_transport(
&self,
account_id: u32,
@@ -571,8 +572,16 @@ impl CommandApi {
ctx.delete_transport(&addr).await
}
// TODO not sure if that's a good API design,
// but I'm also not sure about an alternative - Adding to EnteredLoginParam?
/// Change whether the transport is unpublished.
///
/// Unpublished transports are not advertised to contacts,
/// and self-sent messages are not sent there,
/// so that we don't cause extra messages to the corresponding inbox,
/// but can still receive messages from contacts who don't know the new relay addresses yet.
///
/// The default is true, but when updating,
/// existing secondary transports are set to unpublished,
/// so that an existing transport address doesn't suddenly get spammed with a lot of messages.
async fn set_transport_unpublished(
&self,
account_id: u32,
@@ -580,19 +589,14 @@ impl CommandApi {
unpublished: bool,
) -> Result<()> {
let ctx = self.get_context(account_id).await?;
ctx.set_transport_unpublished(addr, unpublished).await
ctx.set_transport_unpublished(&addr, unpublished).await
}
// TODO not sure if that's a good API design,
// but I'm also not sure about an alternative - Adding to EnteredLoginParam?
async fn get_transport_unpublished(
&self,
account_id: u32,
addr: String,
unpublished: bool,
) -> Result<()> {
/// Check whether the transport is unpublished.
/// See [`Self::set_transport_unpublished`] / `setTransportUnpublished` for details.
async fn is_transport_unpublished(&self, account_id: u32, addr: String) -> Result<bool> {
let ctx = self.get_context(account_id).await?;
ctx.get_transport_unpublished(addr, unpublished).await
ctx.is_transport_unpublished(&addr).await
}
/// Signal an ongoing process to stop.

View File

@@ -827,6 +827,7 @@ impl Context {
"UPDATE config SET value=? WHERE keyname='configured_addr'",
(addr,),
)?;
// TODO set as published
// Update the timestamp for the primary transport
// so it becomes the first in `get_all_self_addrs()` list
@@ -975,7 +976,7 @@ impl Context {
}
/// Returns all published self addresses, newest first.
/// See TODO API
/// See `[Context::set_transport_unpublished]`
pub(crate) async fn get_published_self_addrs(&self) -> Result<Vec<String>> {
self.sql
.query_map_vec(
@@ -999,7 +1000,7 @@ impl Context {
}
/// Returns all published secondary self addresses.
/// See TODO API
/// See `[Context::set_transport_unpublished]`
pub(crate) async fn get_published_secondary_self_addrs(&self) -> Result<Vec<String>> {
self.sql
.query_map_vec(

View File

@@ -110,6 +110,7 @@ impl Context {
/// from a server encoded in a QR code.
/// - [Self::list_transports()] to get a list of all configured transports.
/// - [Self::delete_transport()] to remove a transport.
/// - [Self::set_transport_unpublished()] to set whether contacts see this transport.
pub async fn add_or_update_transport(&self, param: &mut EnteredLoginParam) -> Result<()> {
self.stop_io().await;
let result = self.add_transport_inner(param).await;
@@ -261,6 +262,39 @@ impl Context {
Ok(())
}
/// Change whether the transport is unpublished.
///
/// Unpublished transports are not advertised to contacts,
/// and self-sent messages are not sent there,
/// so that we don't cause extra messages to the corresponding inbox,
/// but can still receive messages from contacts who don't know the new relay addresses yet.
///
/// The default is true, but when updating,
/// existing secondary transports are set to unpublished,
/// so that an existing transport address doesn't suddenly get spammed with a lot of messages.
pub async fn set_transport_unpublished(&self, addr: &str, unpublished: bool) -> Result<()> {
// TODO check if this is the primary transport
self.sql
.execute(
"UPDATE transports SET is_published=? WHERE addr=?",
(!unpublished, addr),
)
.await?;
send_sync_transports(self).await?;
Ok(())
}
/// Check whether the transport is unpublished.
/// See [`Self::set_transport_unpublished`] for details.
pub async fn is_transport_unpublished(&self, addr: &str) -> Result<bool> {
let published: bool = self
.sql
.query_get_value("SELECT is_published FROM transports WHERE addr=?", (addr,))
.await?
.context("is_published is not supposed to be NULL")?;
Ok(!published)
}
async fn inner_configure(&self, param: &EnteredLoginParam) -> Result<()> {
info!(self, "Configure ...");
@@ -627,7 +661,7 @@ async fn configure(ctx: &Context, param: &EnteredLoginParam) -> Result<Option<&'
let provider = configured_param.provider;
configured_param
.clone()
.save_to_transports_table(ctx, param, time())
.save_to_transports_table(ctx, param, time(), true)
.await?;
send_sync_transports(ctx).await?;

View File

@@ -2343,10 +2343,12 @@ ALTER TABLE contacts ADD COLUMN name_normalized TEXT;
.await?;
}
// Add a `published` flag to transports.
// Add an `is_published` flag to transports.
// Unpublished transports are not advertised to contacts,
// and self-sent messages are not sent there.
// The default is published, but when updating,
// and self-sent messages are not sent there,
// so that we don't cause extra messages to the corresponding inbox,
// but can still receive messages from contacts who don't know the new relay addresses yet.
// The default is true, but when updating,
// existing secondary transports are set to unpublished,
// so that an existing transport address doesn't suddenly get spammed with a lot of messages.
inc_and_check(&mut migration_version, 149)?;

View File

@@ -65,6 +65,10 @@ pub(crate) struct TransportData {
/// Timestamp of when the transport was last time (re)configured.
pub(crate) timestamp: i64,
/// Whether the transport is published.
/// See [`Context::set_transport_unpublished`] for details.
pub(crate) is_published: bool,
}
#[derive(Debug, Serialize, Deserialize)]

View File

@@ -561,8 +561,16 @@ impl ConfiguredLoginParam {
context: &Context,
entered_param: &EnteredLoginParam,
timestamp: i64,
is_published: bool,
) -> Result<()> {
save_transport(context, entered_param, &self.into(), timestamp).await?;
save_transport(
context,
entered_param,
&self.into(),
timestamp,
is_published,
)
.await?;
Ok(())
}
@@ -628,6 +636,7 @@ pub(crate) async fn save_transport(
entered_param: &EnteredLoginParam,
configured: &ConfiguredLoginParamJson,
add_timestamp: i64,
is_published: bool,
) -> Result<bool> {
let addr = addr_normalize(&configured.addr);
let configured_addr = context.get_config(Config::ConfiguredAddr).await?;
@@ -635,20 +644,23 @@ pub(crate) async fn save_transport(
let mut modified = context
.sql
.execute(
"INSERT INTO transports (addr, entered_param, configured_param, add_timestamp)
VALUES (?, ?, ?, ?)
"INSERT INTO transports (addr, entered_param, configured_param, add_timestamp, is_published)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT (addr)
DO UPDATE SET entered_param=excluded.entered_param,
configured_param=excluded.configured_param,
add_timestamp=excluded.add_timestamp
add_timestamp=excluded.add_timestamp,
is_published=excluded.is_published,
WHERE entered_param != excluded.entered_param
OR configured_param != excluded.configured_param
OR add_timestamp < excluded.add_timestamp",
OR add_timestamp < excluded.add_timestamp
OR is_published != excluded.is_published",
(
&addr,
serde_json::to_string(entered_param)?,
serde_json::to_string(configured)?,
add_timestamp,
is_published,
),
)
.await?
@@ -685,7 +697,7 @@ pub(crate) async fn send_sync_transports(context: &Context) -> Result<()> {
let transports = context
.sql
.query_map_vec(
"SELECT entered_param, configured_param, add_timestamp
"SELECT entered_param, configured_param, add_timestamp, is_published
FROM transports WHERE id>1",
(),
|row| {
@@ -694,10 +706,12 @@ pub(crate) async fn send_sync_transports(context: &Context) -> Result<()> {
let configured_json: String = row.get(1)?;
let configured: ConfiguredLoginParamJson = serde_json::from_str(&configured_json)?;
let timestamp: i64 = row.get(2)?;
let is_published: bool = row.get(3)?;
Ok(TransportData {
configured,
entered,
timestamp,
is_published,
})
},
)
@@ -736,9 +750,10 @@ pub(crate) async fn sync_transports(
configured,
entered,
timestamp,
is_published,
} in transports
{
modified |= save_transport(context, entered, configured, *timestamp).await?;
modified |= save_transport(context, entered, configured, *timestamp, *is_published).await?;
}
context
@@ -843,7 +858,7 @@ mod tests {
param
.clone()
.save_to_transports_table(&t, &EnteredLoginParam::default(), time())
.save_to_transports_table(&t, &EnteredLoginParam::default(), time(), true)
.await?;
let expected_param = r#"{"addr":"alice@example.org","imap":[{"connection":{"host":"imap.example.com","port":123,"security":"Starttls"},"user":"alice"}],"imap_user":"","imap_password":"foo","smtp":[{"connection":{"host":"smtp.example.com","port":456,"security":"Tls"},"user":"alice@example.org"}],"smtp_user":"","smtp_password":"bar","provider_id":null,"certificate_checks":"Strict","oauth2":false}"#;
assert_eq!(
@@ -1061,7 +1076,7 @@ mod tests {
certificate_checks: ConfiguredCertificateChecks::Automatic,
oauth2: false,
}
.save_to_transports_table(&t, &EnteredLoginParam::default(), time())
.save_to_transports_table(&t, &EnteredLoginParam::default(), time(), true)
.await?;
let (_transport_id, loaded) = ConfiguredLoginParam::load(&t).await?.unwrap();