mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 02:12:13 +00:00
remove old version and fixes duplicated shares
This commit is contained in:
parent
954eedd40e
commit
e1f28e1b87
21 changed files with 567 additions and 9608 deletions
|
|
@ -21,7 +21,7 @@ Future<void> initFlutterCallbacks({
|
|||
required FutureOr<Uint8List?> Function(PlatformInt64)
|
||||
userDiscoveryGetShareForContact,
|
||||
required FutureOr<bool> Function(PlatformInt64, PlatformInt64, Uint8List)
|
||||
userDiscoveryPushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
required FutureOr<List<Uint8List>?> Function(PlatformInt64)
|
||||
userDiscoveryGetOwnPromotionsAfterVersion,
|
||||
required FutureOr<bool> Function(OtherPromotion)
|
||||
|
|
@ -43,7 +43,8 @@ Future<void> initFlutterCallbacks({
|
|||
userDiscoveryVerifyStoredPubkey: userDiscoveryVerifyStoredPubkey,
|
||||
userDiscoverySetShares: userDiscoverySetShares,
|
||||
userDiscoveryGetShareForContact: userDiscoveryGetShareForContact,
|
||||
userDiscoveryPushOwnPromotion: userDiscoveryPushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion:
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
userDiscoveryGetOwnPromotionsAfterVersion:
|
||||
userDiscoveryGetOwnPromotionsAfterVersion,
|
||||
userDiscoveryStoreOtherPromotion: userDiscoveryStoreOtherPromotion,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ abstract class RustLibApi extends BaseApi {
|
|||
required FutureOr<Uint8List?> Function(PlatformInt64)
|
||||
userDiscoveryGetShareForContact,
|
||||
required FutureOr<bool> Function(PlatformInt64, PlatformInt64, Uint8List)
|
||||
userDiscoveryPushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
required FutureOr<List<Uint8List>?> Function(PlatformInt64)
|
||||
userDiscoveryGetOwnPromotionsAfterVersion,
|
||||
required FutureOr<bool> Function(OtherPromotion)
|
||||
|
|
@ -354,7 +354,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
required FutureOr<Uint8List?> Function(PlatformInt64)
|
||||
userDiscoveryGetShareForContact,
|
||||
required FutureOr<bool> Function(PlatformInt64, PlatformInt64, Uint8List)
|
||||
userDiscoveryPushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
required FutureOr<List<Uint8List>?> Function(PlatformInt64)
|
||||
userDiscoveryGetOwnPromotionsAfterVersion,
|
||||
required FutureOr<bool> Function(OtherPromotion)
|
||||
|
|
@ -403,7 +403,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
serializer,
|
||||
);
|
||||
sse_encode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(
|
||||
userDiscoveryPushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
serializer,
|
||||
);
|
||||
sse_encode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException(
|
||||
|
|
@ -453,7 +453,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
userDiscoveryVerifyStoredPubkey,
|
||||
userDiscoverySetShares,
|
||||
userDiscoveryGetShareForContact,
|
||||
userDiscoveryPushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
userDiscoveryGetOwnPromotionsAfterVersion,
|
||||
userDiscoveryStoreOtherPromotion,
|
||||
userDiscoveryGetOtherPromotionsByPublicId,
|
||||
|
|
@ -477,7 +477,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
"userDiscoveryVerifyStoredPubkey",
|
||||
"userDiscoverySetShares",
|
||||
"userDiscoveryGetShareForContact",
|
||||
"userDiscoveryPushOwnPromotion",
|
||||
"userDiscoveryPushOwnPromotionAndClearOldVersion",
|
||||
"userDiscoveryGetOwnPromotionsAfterVersion",
|
||||
"userDiscoveryStoreOtherPromotion",
|
||||
"userDiscoveryGetOtherPromotionsByPublicId",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ Future<void> initFlutterCallbacksForRust() async {
|
|||
userDiscoverySetShares: UserDiscoveryCallbacks.setShares,
|
||||
userDiscoveryGetShareForContact:
|
||||
UserDiscoveryCallbacks.userDiscoveryGetShareForContact,
|
||||
userDiscoveryPushOwnPromotion: UserDiscoveryCallbacks.pushOwnPromotion,
|
||||
userDiscoveryPushOwnPromotionAndClearOldVersion:
|
||||
UserDiscoveryCallbacks.userDiscoveryPushOwnPromotionAndClearOldVersion,
|
||||
userDiscoveryPushNewUserRelation:
|
||||
UserDiscoveryCallbacks.pushNewUserRelation,
|
||||
userDiscoveryGetOwnPromotionsAfterVersion:
|
||||
|
|
|
|||
|
|
@ -110,12 +110,18 @@ class UserDiscoveryCallbacks {
|
|||
});
|
||||
}
|
||||
|
||||
static Future<bool> pushOwnPromotion(
|
||||
static Future<bool> userDiscoveryPushOwnPromotionAndClearOldVersion(
|
||||
int contactId,
|
||||
int version, // Maps to versionId or logic control
|
||||
int version,
|
||||
Uint8List promotion,
|
||||
) async {
|
||||
try {
|
||||
// Old promotions from this users should be removed...
|
||||
await (twonlyDB.update(
|
||||
twonlyDB.userDiscoveryOwnPromotions,
|
||||
)..where((t) => t.contactId.equals(contactId))).write(
|
||||
UserDiscoveryOwnPromotionsCompanion(promotion: Value(Uint8List(0))),
|
||||
);
|
||||
await twonlyDB
|
||||
.into(twonlyDB.userDiscoveryOwnPromotions)
|
||||
.insert(
|
||||
|
|
|
|||
|
|
@ -178,6 +178,40 @@
|
|||
"default_dart": null,
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
},
|
||||
{
|
||||
"name": "user_discovery_excluded",
|
||||
"getter_name": "userDiscoveryExcluded",
|
||||
"moor_type": "bool",
|
||||
"nullable": false,
|
||||
"customConstraints": null,
|
||||
"defaultConstraints": "CHECK (\"user_discovery_excluded\" IN (0, 1))",
|
||||
"dialectAwareDefaultConstraints": {
|
||||
"sqlite": "CHECK (\"user_discovery_excluded\" IN (0, 1))"
|
||||
},
|
||||
"default_dart": "const CustomExpression('0')",
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
},
|
||||
{
|
||||
"name": "media_send_counter",
|
||||
"getter_name": "mediaSendCounter",
|
||||
"moor_type": "int",
|
||||
"nullable": false,
|
||||
"customConstraints": null,
|
||||
"default_dart": "const CustomExpression('0')",
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
},
|
||||
{
|
||||
"name": "media_received_counter",
|
||||
"getter_name": "mediaReceivedCounter",
|
||||
"moor_type": "int",
|
||||
"nullable": false,
|
||||
"customConstraints": null,
|
||||
"default_dart": "const CustomExpression('0')",
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
}
|
||||
],
|
||||
"is_virtual": false,
|
||||
|
|
@ -2126,6 +2160,44 @@
|
|||
"dsl_features": [
|
||||
"unique"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"getter_name": "username",
|
||||
"moor_type": "string",
|
||||
"nullable": true,
|
||||
"customConstraints": null,
|
||||
"default_dart": null,
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
},
|
||||
{
|
||||
"name": "was_shown_to_the_user",
|
||||
"getter_name": "wasShownToTheUser",
|
||||
"moor_type": "bool",
|
||||
"nullable": false,
|
||||
"customConstraints": null,
|
||||
"defaultConstraints": "CHECK (\"was_shown_to_the_user\" IN (0, 1))",
|
||||
"dialectAwareDefaultConstraints": {
|
||||
"sqlite": "CHECK (\"was_shown_to_the_user\" IN (0, 1))"
|
||||
},
|
||||
"default_dart": "const CustomExpression('0')",
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
},
|
||||
{
|
||||
"name": "is_hidden",
|
||||
"getter_name": "isHidden",
|
||||
"moor_type": "bool",
|
||||
"nullable": false,
|
||||
"customConstraints": null,
|
||||
"defaultConstraints": "CHECK (\"is_hidden\" IN (0, 1))",
|
||||
"dialectAwareDefaultConstraints": {
|
||||
"sqlite": "CHECK (\"is_hidden\" IN (0, 1))"
|
||||
},
|
||||
"default_dart": "const CustomExpression('0')",
|
||||
"default_client_dart": null,
|
||||
"dsl_features": []
|
||||
}
|
||||
],
|
||||
"is_virtual": false,
|
||||
|
|
@ -2311,7 +2383,7 @@
|
|||
"constraints": [],
|
||||
"explicit_pk": [
|
||||
"from_contact_id",
|
||||
"promotion_id"
|
||||
"public_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
@ -2458,7 +2530,7 @@
|
|||
"sql": [
|
||||
{
|
||||
"dialect": "sqlite",
|
||||
"sql": "CREATE TABLE IF NOT EXISTS \"contacts\" (\"user_id\" INTEGER NOT NULL, \"username\" TEXT NOT NULL, \"display_name\" TEXT NULL, \"nick_name\" TEXT NULL, \"avatar_svg_compressed\" BLOB NULL, \"sender_profile_counter\" INTEGER NOT NULL DEFAULT 0, \"accepted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"accepted\" IN (0, 1)), \"deleted_by_user\" INTEGER NOT NULL DEFAULT 0 CHECK (\"deleted_by_user\" IN (0, 1)), \"requested\" INTEGER NOT NULL DEFAULT 0 CHECK (\"requested\" IN (0, 1)), \"blocked\" INTEGER NOT NULL DEFAULT 0 CHECK (\"blocked\" IN (0, 1)), \"verified\" INTEGER NOT NULL DEFAULT 0 CHECK (\"verified\" IN (0, 1)), \"account_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"account_deleted\" IN (0, 1)), \"created_at\" INTEGER NOT NULL DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)), \"user_discovery_version\" BLOB NULL, PRIMARY KEY (\"user_id\"));"
|
||||
"sql": "CREATE TABLE IF NOT EXISTS \"contacts\" (\"user_id\" INTEGER NOT NULL, \"username\" TEXT NOT NULL, \"display_name\" TEXT NULL, \"nick_name\" TEXT NULL, \"avatar_svg_compressed\" BLOB NULL, \"sender_profile_counter\" INTEGER NOT NULL DEFAULT 0, \"accepted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"accepted\" IN (0, 1)), \"deleted_by_user\" INTEGER NOT NULL DEFAULT 0 CHECK (\"deleted_by_user\" IN (0, 1)), \"requested\" INTEGER NOT NULL DEFAULT 0 CHECK (\"requested\" IN (0, 1)), \"blocked\" INTEGER NOT NULL DEFAULT 0 CHECK (\"blocked\" IN (0, 1)), \"verified\" INTEGER NOT NULL DEFAULT 0 CHECK (\"verified\" IN (0, 1)), \"account_deleted\" INTEGER NOT NULL DEFAULT 0 CHECK (\"account_deleted\" IN (0, 1)), \"created_at\" INTEGER NOT NULL DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)), \"user_discovery_version\" BLOB NULL, \"user_discovery_excluded\" INTEGER NOT NULL DEFAULT 0 CHECK (\"user_discovery_excluded\" IN (0, 1)), \"media_send_counter\" INTEGER NOT NULL DEFAULT 0, \"media_received_counter\" INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (\"user_id\"));"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -2611,7 +2683,7 @@
|
|||
"sql": [
|
||||
{
|
||||
"dialect": "sqlite",
|
||||
"sql": "CREATE TABLE IF NOT EXISTS \"user_discovery_announced_users\" (\"announced_user_id\" INTEGER NOT NULL, \"announced_public_key\" BLOB NOT NULL, \"public_id\" INTEGER NOT NULL UNIQUE, PRIMARY KEY (\"announced_user_id\"));"
|
||||
"sql": "CREATE TABLE IF NOT EXISTS \"user_discovery_announced_users\" (\"announced_user_id\" INTEGER NOT NULL, \"announced_public_key\" BLOB NOT NULL, \"public_id\" INTEGER NOT NULL UNIQUE, \"username\" TEXT NULL, \"was_shown_to_the_user\" INTEGER NOT NULL DEFAULT 0 CHECK (\"was_shown_to_the_user\" IN (0, 1)), \"is_hidden\" INTEGER NOT NULL DEFAULT 0 CHECK (\"is_hidden\" IN (0, 1)), PRIMARY KEY (\"announced_user_id\"));"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -2629,7 +2701,7 @@
|
|||
"sql": [
|
||||
{
|
||||
"dialect": "sqlite",
|
||||
"sql": "CREATE TABLE IF NOT EXISTS \"user_discovery_other_promotions\" (\"from_contact_id\" INTEGER NOT NULL REFERENCES contacts (user_id) ON DELETE CASCADE, \"promotion_id\" INTEGER NOT NULL, \"public_id\" INTEGER NOT NULL, \"threshold\" INTEGER NOT NULL, \"announcement_share\" BLOB NOT NULL, \"public_key_verified_timestamp\" INTEGER NULL, PRIMARY KEY (\"from_contact_id\", \"promotion_id\"));"
|
||||
"sql": "CREATE TABLE IF NOT EXISTS \"user_discovery_other_promotions\" (\"from_contact_id\" INTEGER NOT NULL REFERENCES contacts (user_id) ON DELETE CASCADE, \"promotion_id\" INTEGER NOT NULL, \"public_id\" INTEGER NOT NULL, \"threshold\" INTEGER NOT NULL, \"announcement_share\" BLOB NOT NULL, \"public_key_verified_timestamp\" INTEGER NULL, PRIMARY KEY (\"from_contact_id\", \"public_id\"));"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -70,7 +70,7 @@ class UserDiscoveryOtherPromotions extends Table {
|
|||
DateTimeColumn get publicKeyVerifiedTimestamp => dateTime().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {fromContactId, promotionId};
|
||||
Set<Column> get primaryKey => {fromContactId, publicId};
|
||||
}
|
||||
|
||||
// unused_shares: Vec<Vec<u8>>,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 15;
|
||||
int get schemaVersion => 12;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(
|
||||
|
|
@ -177,8 +177,6 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
schema.contacts,
|
||||
schema.contacts.userDiscoveryVersion,
|
||||
);
|
||||
},
|
||||
from12To13: (m, schema) async {
|
||||
await m.addColumn(
|
||||
schema.contacts,
|
||||
schema.contacts.mediaReceivedCounter,
|
||||
|
|
@ -187,22 +185,6 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
schema.contacts,
|
||||
schema.contacts.mediaSendCounter,
|
||||
);
|
||||
},
|
||||
from13To14: (m, schema) async {
|
||||
await m.addColumn(
|
||||
schema.userDiscoveryAnnouncedUsers,
|
||||
schema.userDiscoveryAnnouncedUsers.wasShownToTheUser,
|
||||
);
|
||||
await m.addColumn(
|
||||
schema.userDiscoveryAnnouncedUsers,
|
||||
schema.userDiscoveryAnnouncedUsers.isHidden,
|
||||
);
|
||||
await m.addColumn(
|
||||
schema.userDiscoveryAnnouncedUsers,
|
||||
schema.userDiscoveryAnnouncedUsers.username,
|
||||
);
|
||||
},
|
||||
from14To15: (m, schema) async {
|
||||
await m.addColumn(
|
||||
schema.contacts,
|
||||
schema.contacts.userDiscoveryExcluded,
|
||||
|
|
|
|||
|
|
@ -10478,7 +10478,7 @@ class $UserDiscoveryOtherPromotionsTable extends UserDiscoveryOtherPromotions
|
|||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {fromContactId, promotionId};
|
||||
Set<GeneratedColumn> get $primaryKey => {fromContactId, publicId};
|
||||
@override
|
||||
UserDiscoveryOtherPromotion map(
|
||||
Map<String, dynamic> data, {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,7 +28,7 @@ callback_generator! {
|
|||
// UserDiscoveryStore
|
||||
set_shares: (Vec<Vec<u8>>) => bool,
|
||||
get_share_for_contact: (i64) => Option<Vec<u8>>,
|
||||
push_own_promotion: (i64, i64, Vec<u8>) => bool,
|
||||
push_own_promotion_and_clear_old_version: (i64, i64, Vec<u8>) => bool,
|
||||
get_own_promotions_after_version: (i64) => Option<Vec<Vec<u8>>>,
|
||||
store_other_promotion: (OtherPromotion) => bool,
|
||||
get_other_promotions_by_public_id: (i64) => Option<Vec<OtherPromotion>>,
|
||||
|
|
|
|||
|
|
@ -79,13 +79,13 @@ impl UserDiscoveryStore for UserDiscoveryStoreFlutter {
|
|||
}
|
||||
}
|
||||
|
||||
async fn push_own_promotion(
|
||||
async fn push_own_promotion_and_clear_old_version(
|
||||
&self,
|
||||
contact_id: i64,
|
||||
version: u32,
|
||||
promotion: Vec<u8>,
|
||||
) -> Result<()> {
|
||||
(get_callbacks()?.user_discovery.push_own_promotion)(contact_id, version as i64, promotion)
|
||||
(get_callbacks()?.user_discovery.push_own_promotion_and_clear_old_version)(contact_id, version as i64, promotion)
|
||||
.await
|
||||
.then_some(())
|
||||
.ok_or(TwonlyError::DartError.into())
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ let api_user_discovery_verify_signature = decode_DartFn_Inputs_list_prim_u_8_str
|
|||
let api_user_discovery_verify_stored_pubkey = decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_set_shares = decode_DartFn_Inputs_list_list_prim_u_8_strict_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_get_share_for_contact = decode_DartFn_Inputs_i_64_Output_opt_list_prim_u_8_strict_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_push_own_promotion = decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_push_own_promotion_and_clear_old_version = decode_DartFn_Inputs_i_64_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_get_own_promotions_after_version = decode_DartFn_Inputs_i_64_Output_opt_list_list_prim_u_8_strict_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_store_other_promotion = decode_DartFn_Inputs_other_promotion_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_get_other_promotions_by_public_id = decode_DartFn_Inputs_i_64_Output_opt_list_other_promotion_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
|
|
@ -150,7 +150,7 @@ let api_user_discovery_get_contact_version = decode_DartFn_Inputs_i_64_Output_op
|
|||
let api_user_discovery_set_contact_version = decode_DartFn_Inputs_i_64_list_prim_u_8_strict_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));
|
||||
let api_user_discovery_push_new_user_relation = decode_DartFn_Inputs_i_64_announced_user_opt_box_autoadd_i_64_Output_bool_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));deserializer.end(); move |context| {
|
||||
transform_result_sse::<_, ()>((move || {
|
||||
let output_ok = Result::<_,()>::Ok({ crate::bridge::callbacks::init_flutter_callbacks(api_logging_get_stream_sink, api_user_discovery_sign_data, api_user_discovery_verify_signature, api_user_discovery_verify_stored_pubkey, api_user_discovery_set_shares, api_user_discovery_get_share_for_contact, api_user_discovery_push_own_promotion, api_user_discovery_get_own_promotions_after_version, api_user_discovery_store_other_promotion, api_user_discovery_get_other_promotions_by_public_id, api_user_discovery_get_announced_user_by_public_id, api_user_discovery_get_contact_version, api_user_discovery_set_contact_version, api_user_discovery_push_new_user_relation); })?; Ok(output_ok)
|
||||
let output_ok = Result::<_,()>::Ok({ crate::bridge::callbacks::init_flutter_callbacks(api_logging_get_stream_sink, api_user_discovery_sign_data, api_user_discovery_verify_signature, api_user_discovery_verify_stored_pubkey, api_user_discovery_set_shares, api_user_discovery_get_share_for_contact, api_user_discovery_push_own_promotion_and_clear_old_version, api_user_discovery_get_own_promotions_after_version, api_user_discovery_store_other_promotion, api_user_discovery_get_other_promotions_by_public_id, api_user_discovery_get_announced_user_by_public_id, api_user_discovery_get_contact_version, api_user_discovery_set_contact_version, api_user_discovery_push_new_user_relation); })?; Ok(output_ok)
|
||||
})())
|
||||
} })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ pub mod stores;
|
|||
pub mod tests;
|
||||
pub mod traits;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::u8;
|
||||
use blahaj::{Share, Sharks};
|
||||
use prost::Message;
|
||||
|
|
@ -447,7 +447,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
};
|
||||
|
||||
self.store
|
||||
.push_own_promotion(
|
||||
.push_own_promotion_and_clear_old_version(
|
||||
contact_id,
|
||||
config.promotion_version,
|
||||
message.encode_to_vec(),
|
||||
|
|
@ -525,10 +525,21 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
.get_other_promotions_by_public_id(udp.public_id)
|
||||
.await?;
|
||||
|
||||
if promotions.len() < udp.threshold as usize {
|
||||
// Deduplicate shares by their raw bytes to prevent invalid Shamir's Secret Sharing recoveries.
|
||||
// Multiple identical shares (e.g. due to contact resending promotions, or DB duplicate writes)
|
||||
// will cause `recover` to interpolate incorrectly and return garbage bytes.
|
||||
let mut unique_shares_set = HashSet::new();
|
||||
let mut unique_promotions = Vec::new();
|
||||
for p in promotions {
|
||||
if unique_shares_set.insert(p.announcement_share.clone()) {
|
||||
unique_promotions.push(p);
|
||||
}
|
||||
}
|
||||
|
||||
if unique_promotions.len() < udp.threshold as usize {
|
||||
tracing::debug!(
|
||||
"Not enough shares ({} < {}) to decrypt announcement. Waiting for next share.",
|
||||
promotions.len(),
|
||||
"Not enough unique shares ({} < {}) to decrypt announcement. Waiting for next share.",
|
||||
unique_promotions.len(),
|
||||
udp.threshold
|
||||
);
|
||||
return Ok(());
|
||||
|
|
@ -536,7 +547,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
|
||||
tracing::debug!("Enough shares decrypting announcement.");
|
||||
|
||||
let shares: Vec<_> = promotions
|
||||
let shares: Vec<_> = unique_promotions
|
||||
.iter()
|
||||
.map(|x| x.announcement_share.to_owned())
|
||||
.filter_map(|x| Share::try_from(x.as_slice()).ok())
|
||||
|
|
@ -577,7 +588,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
};
|
||||
|
||||
let user_id = self.get_config().await?.user_id;
|
||||
for promotion in promotions {
|
||||
for promotion in unique_promotions {
|
||||
// Do not store the announcement of the users itself.
|
||||
// Or in case the promotion promotes myself
|
||||
if promotion.from_contact_id == announced_user.user_id
|
||||
|
|
|
|||
|
|
@ -66,17 +66,24 @@ impl UserDiscoveryStore for InMemoryStore {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn push_own_promotion(
|
||||
async fn push_own_promotion_and_clear_old_version(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
version: u32,
|
||||
promotion: Vec<u8>,
|
||||
) -> Result<()> {
|
||||
let mut storage = self.storage();
|
||||
// println!("{} != {}", version, storage.promotions.len());
|
||||
|
||||
if version as usize != storage.own_promotions.len() + 1 {
|
||||
return Err(UserDiscoveryError::PushedInvalidVersion);
|
||||
}
|
||||
|
||||
for (old_contact_id, promotion) in storage.own_promotions.iter_mut() {
|
||||
if *old_contact_id == contact_id {
|
||||
promotion.clear();
|
||||
}
|
||||
}
|
||||
|
||||
storage.own_promotions.push((contact_id, promotion));
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ async fn get_with_five_users<S: UserDiscoveryStore + Default + Clone>() -> TestN
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_discovery_dynamic_threshold_in_memory_store() {
|
||||
async fn test_user_discovery_decreased_threshold_in_memory_store() {
|
||||
let _ = pretty_env_logger::try_init();
|
||||
|
||||
let mut network = TestNetwork::<InMemoryStore>::new();
|
||||
|
|
@ -196,6 +196,84 @@ async fn test_user_discovery_dynamic_threshold_in_memory_store() {
|
|||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_discovery_increased_threshold_in_memory_store() {
|
||||
let _ = pretty_env_logger::try_init();
|
||||
|
||||
let mut network = TestNetwork::<InMemoryStore>::new();
|
||||
|
||||
// Start ALICE with a more strict threshold of 3.
|
||||
// David only has 2 paths to Alice (via Bob and Charlie). Since 2 < 3, David cannot discover Alice.
|
||||
network.add_user("ALICE", 2).await;
|
||||
network.add_user("BOB", 2).await;
|
||||
network.add_user("CHARLIE", 2).await;
|
||||
network.add_user("DAVID", 2).await;
|
||||
network.add_user("FRANK", 2).await;
|
||||
|
||||
// Same topology as the initial 5 users
|
||||
network.set_friends("ALICE", &["BOB", "CHARLIE"]);
|
||||
network.set_friends("BOB", &["ALICE", "CHARLIE", "DAVID"]);
|
||||
// CHARLIE IS NOT YET A FRIEND OF DAVID -> DAVID SHOULD NOT BE ABLE TO BE DECODE ALICE
|
||||
network.set_friends("CHARLIE", &["ALICE", "BOB", "FRANK"]);
|
||||
network.set_friends("DAVID", &["BOB", "CHARLIE"]);
|
||||
network.set_friends("FRANK", &["CHARLIE"]);
|
||||
|
||||
let david_idx = network.ids_by_name["DAVID"];
|
||||
let alice_idx = network.ids_by_name["ALICE"];
|
||||
|
||||
// Phase 1: Exchange with ALICE threshold = 2
|
||||
step0_exchange_random::<InMemoryStore>(&network).await;
|
||||
step1_verify_no_new_messages::<InMemoryStore>(&network).await;
|
||||
|
||||
// DAVID should NOT know ALICE yet because ALICE's threshold is 2, and David has only 1 shares.
|
||||
{
|
||||
let david_knows = network.uds[david_idx]
|
||||
.get_all_announced_users()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let knows_alice = david_knows
|
||||
.iter()
|
||||
.any(|(u, _)| u.user_id == alice_idx as UserID);
|
||||
|
||||
assert!(!knows_alice, "David should not know Alice yet because Alice's threshold is 3 and David only receives 2 shares");
|
||||
}
|
||||
|
||||
// Phase 2: Update ALICE's threshold to 3
|
||||
network.uds[alice_idx]
|
||||
.initialize_or_update(3, alice_idx as UserID, vec![alice_idx as u8; 32])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// ALICE's new announcement with threshold 3 should propagate further.
|
||||
// This SHOULD REPLACE THE OLD VERSION...
|
||||
step0_exchange_random::<InMemoryStore>(&network).await;
|
||||
step1_verify_no_new_messages::<InMemoryStore>(&network).await;
|
||||
|
||||
// Now Charlie is a friend of David, so he should exchange ALICE with him
|
||||
|
||||
network.set_friends("CHARLIE", &["ALICE", "BOB", "DAVID", "FRANK"]);
|
||||
|
||||
// ALICE's new announcement with threshold 3 should propagate further.
|
||||
// This SHOULD REPLACE THE OLD VERSION...
|
||||
step0_exchange_random::<InMemoryStore>(&network).await;
|
||||
step1_verify_no_new_messages::<InMemoryStore>(&network).await;
|
||||
|
||||
// DAVID should still NOT know ALICE yet because ALICE's new threshold is 3, and David has only 2 shares.
|
||||
{
|
||||
let david_knows = network.uds[david_idx]
|
||||
.get_all_announced_users()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let knows_alice = david_knows
|
||||
.iter()
|
||||
.any(|(u, _)| u.user_id == alice_idx as UserID);
|
||||
|
||||
assert!(!knows_alice, "David should not know Alice yet because Alice's threshold is 3 and David only receives 2 shares");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_discovery_in_memory_store() {
|
||||
let _ = pretty_env_logger::try_init();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub trait UserDiscoveryStore {
|
|||
contact_id: UserID,
|
||||
) -> impl Future<Output = Result<Vec<u8>>> + Send;
|
||||
|
||||
fn push_own_promotion(
|
||||
fn push_own_promotion_and_clear_old_version(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
version: u32,
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ import 'schema_v9.dart' as v9;
|
|||
import 'schema_v10.dart' as v10;
|
||||
import 'schema_v11.dart' as v11;
|
||||
import 'schema_v12.dart' as v12;
|
||||
import 'schema_v13.dart' as v13;
|
||||
import 'schema_v14.dart' as v14;
|
||||
import 'schema_v15.dart' as v15;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
|
|
@ -48,32 +45,10 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||
return v11.DatabaseAtV11(db);
|
||||
case 12:
|
||||
return v12.DatabaseAtV12(db);
|
||||
case 13:
|
||||
return v13.DatabaseAtV13(db);
|
||||
case 14:
|
||||
return v14.DatabaseAtV14(db);
|
||||
case 15:
|
||||
return v15.DatabaseAtV15(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,34 @@ class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
|||
requiredDuringInsert: false,
|
||||
$customConstraints: 'NULL',
|
||||
);
|
||||
late final GeneratedColumn<int> userDiscoveryExcluded = GeneratedColumn<int>(
|
||||
'user_discovery_excluded',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints:
|
||||
'NOT NULL DEFAULT 0 CHECK (user_discovery_excluded IN (0, 1))',
|
||||
defaultValue: const CustomExpression('0'),
|
||||
);
|
||||
late final GeneratedColumn<int> mediaSendCounter = GeneratedColumn<int>(
|
||||
'media_send_counter',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: 'NOT NULL DEFAULT 0',
|
||||
defaultValue: const CustomExpression('0'),
|
||||
);
|
||||
late final GeneratedColumn<int> mediaReceivedCounter = GeneratedColumn<int>(
|
||||
'media_received_counter',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: 'NOT NULL DEFAULT 0',
|
||||
defaultValue: const CustomExpression('0'),
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
userId,
|
||||
|
|
@ -151,6 +179,9 @@ class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
|||
accountDeleted,
|
||||
createdAt,
|
||||
userDiscoveryVersion,
|
||||
userDiscoveryExcluded,
|
||||
mediaSendCounter,
|
||||
mediaReceivedCounter,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
|
|
@ -219,6 +250,18 @@ class Contacts extends Table with TableInfo<Contacts, ContactsData> {
|
|||
DriftSqlType.blob,
|
||||
data['${effectivePrefix}user_discovery_version'],
|
||||
),
|
||||
userDiscoveryExcluded: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}user_discovery_excluded'],
|
||||
)!,
|
||||
mediaSendCounter: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}media_send_counter'],
|
||||
)!,
|
||||
mediaReceivedCounter: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}media_received_counter'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -248,6 +291,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
final int accountDeleted;
|
||||
final int createdAt;
|
||||
final i2.Uint8List? userDiscoveryVersion;
|
||||
final int userDiscoveryExcluded;
|
||||
final int mediaSendCounter;
|
||||
final int mediaReceivedCounter;
|
||||
const ContactsData({
|
||||
required this.userId,
|
||||
required this.username,
|
||||
|
|
@ -263,6 +309,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
required this.accountDeleted,
|
||||
required this.createdAt,
|
||||
this.userDiscoveryVersion,
|
||||
required this.userDiscoveryExcluded,
|
||||
required this.mediaSendCounter,
|
||||
required this.mediaReceivedCounter,
|
||||
});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
|
|
@ -293,6 +342,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
userDiscoveryVersion,
|
||||
);
|
||||
}
|
||||
map['user_discovery_excluded'] = Variable<int>(userDiscoveryExcluded);
|
||||
map['media_send_counter'] = Variable<int>(mediaSendCounter);
|
||||
map['media_received_counter'] = Variable<int>(mediaReceivedCounter);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -320,6 +372,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
userDiscoveryVersion: userDiscoveryVersion == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(userDiscoveryVersion),
|
||||
userDiscoveryExcluded: Value(userDiscoveryExcluded),
|
||||
mediaSendCounter: Value(mediaSendCounter),
|
||||
mediaReceivedCounter: Value(mediaReceivedCounter),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +404,13 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
userDiscoveryVersion: serializer.fromJson<i2.Uint8List?>(
|
||||
json['userDiscoveryVersion'],
|
||||
),
|
||||
userDiscoveryExcluded: serializer.fromJson<int>(
|
||||
json['userDiscoveryExcluded'],
|
||||
),
|
||||
mediaSendCounter: serializer.fromJson<int>(json['mediaSendCounter']),
|
||||
mediaReceivedCounter: serializer.fromJson<int>(
|
||||
json['mediaReceivedCounter'],
|
||||
),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
|
@ -373,6 +435,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
'userDiscoveryVersion': serializer.toJson<i2.Uint8List?>(
|
||||
userDiscoveryVersion,
|
||||
),
|
||||
'userDiscoveryExcluded': serializer.toJson<int>(userDiscoveryExcluded),
|
||||
'mediaSendCounter': serializer.toJson<int>(mediaSendCounter),
|
||||
'mediaReceivedCounter': serializer.toJson<int>(mediaReceivedCounter),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -391,6 +456,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
int? accountDeleted,
|
||||
int? createdAt,
|
||||
Value<i2.Uint8List?> userDiscoveryVersion = const Value.absent(),
|
||||
int? userDiscoveryExcluded,
|
||||
int? mediaSendCounter,
|
||||
int? mediaReceivedCounter,
|
||||
}) => ContactsData(
|
||||
userId: userId ?? this.userId,
|
||||
username: username ?? this.username,
|
||||
|
|
@ -410,6 +478,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
userDiscoveryVersion: userDiscoveryVersion.present
|
||||
? userDiscoveryVersion.value
|
||||
: this.userDiscoveryVersion,
|
||||
userDiscoveryExcluded: userDiscoveryExcluded ?? this.userDiscoveryExcluded,
|
||||
mediaSendCounter: mediaSendCounter ?? this.mediaSendCounter,
|
||||
mediaReceivedCounter: mediaReceivedCounter ?? this.mediaReceivedCounter,
|
||||
);
|
||||
ContactsData copyWithCompanion(ContactsCompanion data) {
|
||||
return ContactsData(
|
||||
|
|
@ -439,6 +510,15 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
userDiscoveryVersion: data.userDiscoveryVersion.present
|
||||
? data.userDiscoveryVersion.value
|
||||
: this.userDiscoveryVersion,
|
||||
userDiscoveryExcluded: data.userDiscoveryExcluded.present
|
||||
? data.userDiscoveryExcluded.value
|
||||
: this.userDiscoveryExcluded,
|
||||
mediaSendCounter: data.mediaSendCounter.present
|
||||
? data.mediaSendCounter.value
|
||||
: this.mediaSendCounter,
|
||||
mediaReceivedCounter: data.mediaReceivedCounter.present
|
||||
? data.mediaReceivedCounter.value
|
||||
: this.mediaReceivedCounter,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -458,7 +538,10 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
..write('verified: $verified, ')
|
||||
..write('accountDeleted: $accountDeleted, ')
|
||||
..write('createdAt: $createdAt, ')
|
||||
..write('userDiscoveryVersion: $userDiscoveryVersion')
|
||||
..write('userDiscoveryVersion: $userDiscoveryVersion, ')
|
||||
..write('userDiscoveryExcluded: $userDiscoveryExcluded, ')
|
||||
..write('mediaSendCounter: $mediaSendCounter, ')
|
||||
..write('mediaReceivedCounter: $mediaReceivedCounter')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -479,6 +562,9 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
accountDeleted,
|
||||
createdAt,
|
||||
$driftBlobEquality.hash(userDiscoveryVersion),
|
||||
userDiscoveryExcluded,
|
||||
mediaSendCounter,
|
||||
mediaReceivedCounter,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
|
|
@ -503,7 +589,10 @@ class ContactsData extends DataClass implements Insertable<ContactsData> {
|
|||
$driftBlobEquality.equals(
|
||||
other.userDiscoveryVersion,
|
||||
this.userDiscoveryVersion,
|
||||
));
|
||||
) &&
|
||||
other.userDiscoveryExcluded == this.userDiscoveryExcluded &&
|
||||
other.mediaSendCounter == this.mediaSendCounter &&
|
||||
other.mediaReceivedCounter == this.mediaReceivedCounter);
|
||||
}
|
||||
|
||||
class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
||||
|
|
@ -521,6 +610,9 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
final Value<int> accountDeleted;
|
||||
final Value<int> createdAt;
|
||||
final Value<i2.Uint8List?> userDiscoveryVersion;
|
||||
final Value<int> userDiscoveryExcluded;
|
||||
final Value<int> mediaSendCounter;
|
||||
final Value<int> mediaReceivedCounter;
|
||||
const ContactsCompanion({
|
||||
this.userId = const Value.absent(),
|
||||
this.username = const Value.absent(),
|
||||
|
|
@ -536,6 +628,9 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
this.accountDeleted = const Value.absent(),
|
||||
this.createdAt = const Value.absent(),
|
||||
this.userDiscoveryVersion = const Value.absent(),
|
||||
this.userDiscoveryExcluded = const Value.absent(),
|
||||
this.mediaSendCounter = const Value.absent(),
|
||||
this.mediaReceivedCounter = const Value.absent(),
|
||||
});
|
||||
ContactsCompanion.insert({
|
||||
this.userId = const Value.absent(),
|
||||
|
|
@ -552,6 +647,9 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
this.accountDeleted = const Value.absent(),
|
||||
this.createdAt = const Value.absent(),
|
||||
this.userDiscoveryVersion = const Value.absent(),
|
||||
this.userDiscoveryExcluded = const Value.absent(),
|
||||
this.mediaSendCounter = const Value.absent(),
|
||||
this.mediaReceivedCounter = const Value.absent(),
|
||||
}) : username = Value(username);
|
||||
static Insertable<ContactsData> custom({
|
||||
Expression<int>? userId,
|
||||
|
|
@ -568,6 +666,9 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
Expression<int>? accountDeleted,
|
||||
Expression<int>? createdAt,
|
||||
Expression<i2.Uint8List>? userDiscoveryVersion,
|
||||
Expression<int>? userDiscoveryExcluded,
|
||||
Expression<int>? mediaSendCounter,
|
||||
Expression<int>? mediaReceivedCounter,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (userId != null) 'user_id': userId,
|
||||
|
|
@ -587,6 +688,11 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
if (createdAt != null) 'created_at': createdAt,
|
||||
if (userDiscoveryVersion != null)
|
||||
'user_discovery_version': userDiscoveryVersion,
|
||||
if (userDiscoveryExcluded != null)
|
||||
'user_discovery_excluded': userDiscoveryExcluded,
|
||||
if (mediaSendCounter != null) 'media_send_counter': mediaSendCounter,
|
||||
if (mediaReceivedCounter != null)
|
||||
'media_received_counter': mediaReceivedCounter,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -605,6 +711,9 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
Value<int>? accountDeleted,
|
||||
Value<int>? createdAt,
|
||||
Value<i2.Uint8List?>? userDiscoveryVersion,
|
||||
Value<int>? userDiscoveryExcluded,
|
||||
Value<int>? mediaSendCounter,
|
||||
Value<int>? mediaReceivedCounter,
|
||||
}) {
|
||||
return ContactsCompanion(
|
||||
userId: userId ?? this.userId,
|
||||
|
|
@ -621,6 +730,10 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
accountDeleted: accountDeleted ?? this.accountDeleted,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
userDiscoveryVersion: userDiscoveryVersion ?? this.userDiscoveryVersion,
|
||||
userDiscoveryExcluded:
|
||||
userDiscoveryExcluded ?? this.userDiscoveryExcluded,
|
||||
mediaSendCounter: mediaSendCounter ?? this.mediaSendCounter,
|
||||
mediaReceivedCounter: mediaReceivedCounter ?? this.mediaReceivedCounter,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -673,6 +786,17 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
userDiscoveryVersion.value,
|
||||
);
|
||||
}
|
||||
if (userDiscoveryExcluded.present) {
|
||||
map['user_discovery_excluded'] = Variable<int>(
|
||||
userDiscoveryExcluded.value,
|
||||
);
|
||||
}
|
||||
if (mediaSendCounter.present) {
|
||||
map['media_send_counter'] = Variable<int>(mediaSendCounter.value);
|
||||
}
|
||||
if (mediaReceivedCounter.present) {
|
||||
map['media_received_counter'] = Variable<int>(mediaReceivedCounter.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +816,10 @@ class ContactsCompanion extends UpdateCompanion<ContactsData> {
|
|||
..write('verified: $verified, ')
|
||||
..write('accountDeleted: $accountDeleted, ')
|
||||
..write('createdAt: $createdAt, ')
|
||||
..write('userDiscoveryVersion: $userDiscoveryVersion')
|
||||
..write('userDiscoveryVersion: $userDiscoveryVersion, ')
|
||||
..write('userDiscoveryExcluded: $userDiscoveryExcluded, ')
|
||||
..write('mediaSendCounter: $mediaSendCounter, ')
|
||||
..write('mediaReceivedCounter: $mediaReceivedCounter')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -7813,11 +7940,41 @@ class UserDiscoveryAnnouncedUsers extends Table
|
|||
requiredDuringInsert: true,
|
||||
$customConstraints: 'NOT NULL UNIQUE',
|
||||
);
|
||||
late final GeneratedColumn<String> username = GeneratedColumn<String>(
|
||||
'username',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: 'NULL',
|
||||
);
|
||||
late final GeneratedColumn<int> wasShownToTheUser = GeneratedColumn<int>(
|
||||
'was_shown_to_the_user',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints:
|
||||
'NOT NULL DEFAULT 0 CHECK (was_shown_to_the_user IN (0, 1))',
|
||||
defaultValue: const CustomExpression('0'),
|
||||
);
|
||||
late final GeneratedColumn<int> isHidden = GeneratedColumn<int>(
|
||||
'is_hidden',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_hidden IN (0, 1))',
|
||||
defaultValue: const CustomExpression('0'),
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
announcedUserId,
|
||||
announcedPublicKey,
|
||||
publicId,
|
||||
username,
|
||||
wasShownToTheUser,
|
||||
isHidden,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
|
|
@ -7845,6 +8002,18 @@ class UserDiscoveryAnnouncedUsers extends Table
|
|||
DriftSqlType.int,
|
||||
data['${effectivePrefix}public_id'],
|
||||
)!,
|
||||
username: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}username'],
|
||||
),
|
||||
wasShownToTheUser: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}was_shown_to_the_user'],
|
||||
)!,
|
||||
isHidden: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}is_hidden'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -7866,10 +8035,16 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
final int announcedUserId;
|
||||
final i2.Uint8List announcedPublicKey;
|
||||
final int publicId;
|
||||
final String? username;
|
||||
final int wasShownToTheUser;
|
||||
final int isHidden;
|
||||
const UserDiscoveryAnnouncedUsersData({
|
||||
required this.announcedUserId,
|
||||
required this.announcedPublicKey,
|
||||
required this.publicId,
|
||||
this.username,
|
||||
required this.wasShownToTheUser,
|
||||
required this.isHidden,
|
||||
});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
|
|
@ -7877,6 +8052,11 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
map['announced_user_id'] = Variable<int>(announcedUserId);
|
||||
map['announced_public_key'] = Variable<i2.Uint8List>(announcedPublicKey);
|
||||
map['public_id'] = Variable<int>(publicId);
|
||||
if (!nullToAbsent || username != null) {
|
||||
map['username'] = Variable<String>(username);
|
||||
}
|
||||
map['was_shown_to_the_user'] = Variable<int>(wasShownToTheUser);
|
||||
map['is_hidden'] = Variable<int>(isHidden);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -7885,6 +8065,11 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
announcedUserId: Value(announcedUserId),
|
||||
announcedPublicKey: Value(announcedPublicKey),
|
||||
publicId: Value(publicId),
|
||||
username: username == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(username),
|
||||
wasShownToTheUser: Value(wasShownToTheUser),
|
||||
isHidden: Value(isHidden),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -7899,6 +8084,9 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
json['announcedPublicKey'],
|
||||
),
|
||||
publicId: serializer.fromJson<int>(json['publicId']),
|
||||
username: serializer.fromJson<String?>(json['username']),
|
||||
wasShownToTheUser: serializer.fromJson<int>(json['wasShownToTheUser']),
|
||||
isHidden: serializer.fromJson<int>(json['isHidden']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
|
@ -7908,6 +8096,9 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
'announcedUserId': serializer.toJson<int>(announcedUserId),
|
||||
'announcedPublicKey': serializer.toJson<i2.Uint8List>(announcedPublicKey),
|
||||
'publicId': serializer.toJson<int>(publicId),
|
||||
'username': serializer.toJson<String?>(username),
|
||||
'wasShownToTheUser': serializer.toJson<int>(wasShownToTheUser),
|
||||
'isHidden': serializer.toJson<int>(isHidden),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -7915,10 +8106,16 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
int? announcedUserId,
|
||||
i2.Uint8List? announcedPublicKey,
|
||||
int? publicId,
|
||||
Value<String?> username = const Value.absent(),
|
||||
int? wasShownToTheUser,
|
||||
int? isHidden,
|
||||
}) => UserDiscoveryAnnouncedUsersData(
|
||||
announcedUserId: announcedUserId ?? this.announcedUserId,
|
||||
announcedPublicKey: announcedPublicKey ?? this.announcedPublicKey,
|
||||
publicId: publicId ?? this.publicId,
|
||||
username: username.present ? username.value : this.username,
|
||||
wasShownToTheUser: wasShownToTheUser ?? this.wasShownToTheUser,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
);
|
||||
UserDiscoveryAnnouncedUsersData copyWithCompanion(
|
||||
UserDiscoveryAnnouncedUsersCompanion data,
|
||||
|
|
@ -7931,6 +8128,11 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
? data.announcedPublicKey.value
|
||||
: this.announcedPublicKey,
|
||||
publicId: data.publicId.present ? data.publicId.value : this.publicId,
|
||||
username: data.username.present ? data.username.value : this.username,
|
||||
wasShownToTheUser: data.wasShownToTheUser.present
|
||||
? data.wasShownToTheUser.value
|
||||
: this.wasShownToTheUser,
|
||||
isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -7939,7 +8141,10 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
return (StringBuffer('UserDiscoveryAnnouncedUsersData(')
|
||||
..write('announcedUserId: $announcedUserId, ')
|
||||
..write('announcedPublicKey: $announcedPublicKey, ')
|
||||
..write('publicId: $publicId')
|
||||
..write('publicId: $publicId, ')
|
||||
..write('username: $username, ')
|
||||
..write('wasShownToTheUser: $wasShownToTheUser, ')
|
||||
..write('isHidden: $isHidden')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -7949,6 +8154,9 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
announcedUserId,
|
||||
$driftBlobEquality.hash(announcedPublicKey),
|
||||
publicId,
|
||||
username,
|
||||
wasShownToTheUser,
|
||||
isHidden,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
|
|
@ -7959,7 +8167,10 @@ class UserDiscoveryAnnouncedUsersData extends DataClass
|
|||
other.announcedPublicKey,
|
||||
this.announcedPublicKey,
|
||||
) &&
|
||||
other.publicId == this.publicId);
|
||||
other.publicId == this.publicId &&
|
||||
other.username == this.username &&
|
||||
other.wasShownToTheUser == this.wasShownToTheUser &&
|
||||
other.isHidden == this.isHidden);
|
||||
}
|
||||
|
||||
class UserDiscoveryAnnouncedUsersCompanion
|
||||
|
|
@ -7967,27 +8178,42 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
final Value<int> announcedUserId;
|
||||
final Value<i2.Uint8List> announcedPublicKey;
|
||||
final Value<int> publicId;
|
||||
final Value<String?> username;
|
||||
final Value<int> wasShownToTheUser;
|
||||
final Value<int> isHidden;
|
||||
const UserDiscoveryAnnouncedUsersCompanion({
|
||||
this.announcedUserId = const Value.absent(),
|
||||
this.announcedPublicKey = const Value.absent(),
|
||||
this.publicId = const Value.absent(),
|
||||
this.username = const Value.absent(),
|
||||
this.wasShownToTheUser = const Value.absent(),
|
||||
this.isHidden = const Value.absent(),
|
||||
});
|
||||
UserDiscoveryAnnouncedUsersCompanion.insert({
|
||||
this.announcedUserId = const Value.absent(),
|
||||
required i2.Uint8List announcedPublicKey,
|
||||
required int publicId,
|
||||
this.username = const Value.absent(),
|
||||
this.wasShownToTheUser = const Value.absent(),
|
||||
this.isHidden = const Value.absent(),
|
||||
}) : announcedPublicKey = Value(announcedPublicKey),
|
||||
publicId = Value(publicId);
|
||||
static Insertable<UserDiscoveryAnnouncedUsersData> custom({
|
||||
Expression<int>? announcedUserId,
|
||||
Expression<i2.Uint8List>? announcedPublicKey,
|
||||
Expression<int>? publicId,
|
||||
Expression<String>? username,
|
||||
Expression<int>? wasShownToTheUser,
|
||||
Expression<int>? isHidden,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (announcedUserId != null) 'announced_user_id': announcedUserId,
|
||||
if (announcedPublicKey != null)
|
||||
'announced_public_key': announcedPublicKey,
|
||||
if (publicId != null) 'public_id': publicId,
|
||||
if (username != null) 'username': username,
|
||||
if (wasShownToTheUser != null) 'was_shown_to_the_user': wasShownToTheUser,
|
||||
if (isHidden != null) 'is_hidden': isHidden,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -7995,11 +8221,17 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
Value<int>? announcedUserId,
|
||||
Value<i2.Uint8List>? announcedPublicKey,
|
||||
Value<int>? publicId,
|
||||
Value<String?>? username,
|
||||
Value<int>? wasShownToTheUser,
|
||||
Value<int>? isHidden,
|
||||
}) {
|
||||
return UserDiscoveryAnnouncedUsersCompanion(
|
||||
announcedUserId: announcedUserId ?? this.announcedUserId,
|
||||
announcedPublicKey: announcedPublicKey ?? this.announcedPublicKey,
|
||||
publicId: publicId ?? this.publicId,
|
||||
username: username ?? this.username,
|
||||
wasShownToTheUser: wasShownToTheUser ?? this.wasShownToTheUser,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -8017,6 +8249,15 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
if (publicId.present) {
|
||||
map['public_id'] = Variable<int>(publicId.value);
|
||||
}
|
||||
if (username.present) {
|
||||
map['username'] = Variable<String>(username.value);
|
||||
}
|
||||
if (wasShownToTheUser.present) {
|
||||
map['was_shown_to_the_user'] = Variable<int>(wasShownToTheUser.value);
|
||||
}
|
||||
if (isHidden.present) {
|
||||
map['is_hidden'] = Variable<int>(isHidden.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -8025,7 +8266,10 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
return (StringBuffer('UserDiscoveryAnnouncedUsersCompanion(')
|
||||
..write('announcedUserId: $announcedUserId, ')
|
||||
..write('announcedPublicKey: $announcedPublicKey, ')
|
||||
..write('publicId: $publicId')
|
||||
..write('publicId: $publicId, ')
|
||||
..write('username: $username, ')
|
||||
..write('wasShownToTheUser: $wasShownToTheUser, ')
|
||||
..write('isHidden: $isHidden')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -8377,7 +8621,7 @@ class UserDiscoveryOtherPromotions extends Table
|
|||
String get actualTableName => $name;
|
||||
static const String $name = 'user_discovery_other_promotions';
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {fromContactId, promotionId};
|
||||
Set<GeneratedColumn> get $primaryKey => {fromContactId, publicId};
|
||||
@override
|
||||
UserDiscoveryOtherPromotionsData map(
|
||||
Map<String, dynamic> data, {
|
||||
|
|
@ -8419,7 +8663,7 @@ class UserDiscoveryOtherPromotions extends Table
|
|||
|
||||
@override
|
||||
List<String> get customConstraints => const [
|
||||
'PRIMARY KEY(from_contact_id, promotion_id)',
|
||||
'PRIMARY KEY(from_contact_id, public_id)',
|
||||
];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue