feat: finish latest wrappers fix tests and continue building default generation functions. refactor defaults to be used if no stored data blob in DB

This commit is contained in:
0x330a 2023-03-03 16:41:57 +11:00
parent c1434648dc
commit 2a701f2cc3
No known key found for this signature in database
GPG Key ID: 267811D6E6A2698C
6 changed files with 70 additions and 41 deletions

View File

@ -8,8 +8,8 @@ import network.loki.messenger.libsession_util.UserProfile
import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.ConfigFactoryProtocol
import org.session.libsession.utilities.ConfigFactoryUpdateListener import org.session.libsession.utilities.ConfigFactoryUpdateListener
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.ConfigDatabase import org.thoughtcrime.securesms.database.ConfigDatabase
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import java.util.concurrent.ConcurrentSkipListSet import java.util.concurrent.ConcurrentSkipListSet
class ConfigFactory(private val context: Context, class ConfigFactory(private val context: Context,
@ -42,14 +42,14 @@ class ConfigFactory(private val context: Context,
override val user: UserProfile? get() = synchronized(userLock) { override val user: UserProfile? get() = synchronized(userLock) {
if (_userConfig == null) { if (_userConfig == null) {
Log.d("Loki-DBG", "Getting user info")
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
Log.d("Loki-DBG", "Getting user configs and hashes")
val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey) val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey)
_userConfig = if (userDump != null) { _userConfig = if (userDump != null) {
UserProfile.newInstance(secretKey, userDump) UserProfile.newInstance(secretKey, userDump)
} else { } else {
UserProfile.newInstance(secretKey) ConfigurationMessageUtilities.generateUserProfileConfigDump()?.let { dump ->
UserProfile.newInstance(secretKey, dump)
} ?: UserProfile.newInstance(secretKey)
} }
} }
_userConfig _userConfig
@ -62,7 +62,9 @@ class ConfigFactory(private val context: Context,
_contacts = if (contactsDump != null) { _contacts = if (contactsDump != null) {
Contacts.newInstance(secretKey, contactsDump) Contacts.newInstance(secretKey, contactsDump)
} else { } else {
Contacts.newInstance(secretKey) ConfigurationMessageUtilities.generateContactConfigDump()?.let { dump ->
Contacts.newInstance(secretKey, dump)
} ?: Contacts.newInstance(secretKey)
} }
} }
_contacts _contacts
@ -75,7 +77,10 @@ class ConfigFactory(private val context: Context,
_convoVolatileConfig = if (convoDump != null) { _convoVolatileConfig = if (convoDump != null) {
ConversationVolatileConfig.newInstance(secretKey, convoDump) ConversationVolatileConfig.newInstance(secretKey, convoDump)
} else { } else {
ConversationVolatileConfig.newInstance(secretKey) // TODO: generate convo volatile config here
ConfigurationMessageUtilities.generateConversationVolatileDump(context)?.let { dump ->
ConversationVolatileConfig.newInstance(secretKey, dump)
} ?: ConversationVolatileConfig.newInstance(secretKey)
} }
} }
_convoVolatileConfig _convoVolatileConfig

View File

@ -15,6 +15,7 @@ import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.utilities.SessionId
import org.session.libsession.utilities.Address import org.session.libsession.utilities.Address
import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
@ -116,7 +117,7 @@ object ConfigurationMessageUtilities {
return dump return dump
} }
fun generateContactConfigDump(context: Context): ByteArray? { fun generateContactConfigDump(): ByteArray? {
val secretKey = maybeUserSecretKey() ?: return null val secretKey = maybeUserSecretKey() ?: return null
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val localUserKey = storage.getUserPublicKey() ?: return null val localUserKey = storage.getUserPublicKey() ?: return null
@ -142,7 +143,7 @@ object ConfigurationMessageUtilities {
approved = settings.isApproved, approved = settings.isApproved,
approvedMe = settings.hasApprovedMe(), approvedMe = settings.hasApprovedMe(),
profilePicture = userPic ?: UserPic.DEFAULT, profilePicture = userPic ?: UserPic.DEFAULT,
priority = 0 // TODO: read this in from a pinned priority priority = if ()
) )
contactConfig.set(contactInfo) contactConfig.set(contactInfo)
} }
@ -154,7 +155,6 @@ object ConfigurationMessageUtilities {
fun generateConversationVolatileDump(context: Context): ByteArray? { fun generateConversationVolatileDump(context: Context): ByteArray? {
val secretKey = maybeUserSecretKey() ?: return null val secretKey = maybeUserSecretKey() ?: return null
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val localUserKey = storage.getUserPublicKey() ?: return null
val convoConfig = ConversationVolatileConfig.newInstance(secretKey) val convoConfig = ConversationVolatileConfig.newInstance(secretKey)
val threadDb = DatabaseComponent.get(context).threadDatabase() val threadDb = DatabaseComponent.get(context).threadDatabase()
threadDb.approvedConversationList.use { cursor -> threadDb.approvedConversationList.use { cursor ->
@ -172,9 +172,18 @@ object ConfigurationMessageUtilities {
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize()) val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
convoConfig.getOrConstructLegacyGroup(groupPublicKey) convoConfig.getOrConstructLegacyGroup(groupPublicKey)
} }
recipient.isContactRecipient -> convoConfig.getOrConstructOneToOne(recipient.address.serialize()) recipient.isContactRecipient -> {
val sessionId = SessionId(recipient.address.serialize())
if (recipient.isLocalNumber) null // this is handled by the user profile NTS data
else convoConfig.getOrConstructOneToOne(recipient.address.serialize())
}
else -> null else -> null
} ?: continue }
if (contact == null) {
current = reader.next
continue
}
contact.lastRead = current.lastSeen contact.lastRead = current.lastSeen
contact.unread = false // TODO: make the forced unread work at DB level contact.unread = false // TODO: make the forced unread work at DB level
convoConfig.set(contact) convoConfig.set(contact)

@ -1 +1 @@
Subproject commit 5a7569861d1b39d866ba7d8c7440db1908e84798 Subproject commit f76fee84d76bf0437e57a5e4ae15ba76a31e0ca6

View File

@ -188,6 +188,7 @@ class InstrumentedTests {
userProfile.setName("Kallie") userProfile.setName("Kallie")
val newUserPic = UserPic("http://example.org/omg-pic-123.bmp", "secret78901234567890123456789012".encodeToByteArray()) val newUserPic = UserPic("http://example.org/omg-pic-123.bmp", "secret78901234567890123456789012".encodeToByteArray())
userProfile.setPic(newUserPic) userProfile.setPic(newUserPic)
userProfile.setNtsPriority(9)
// Retrieve them just to make sure they set properly: // Retrieve them just to make sure they set properly:
assertEquals("Kallie", userProfile.getName()) assertEquals("Kallie", userProfile.getName())
@ -205,20 +206,22 @@ class InstrumentedTests {
Hex.fromStringCondensed("ea173b57beca8af18c3519a7bbf69c3e7a05d1c049fa9558341d8ebb48b0c965") Hex.fromStringCondensed("ea173b57beca8af18c3519a7bbf69c3e7a05d1c049fa9558341d8ebb48b0c965")
val expectedPush1Decrypted = ("d" + val expectedPush1Decrypted = ("d" +
"1:#" + "i1e"+ "1:#"+ "i1e" +
"1:&" + "d"+ "1:&"+ "d"+
"1:n" + "6:Kallie"+ "1:+"+ "i9e"+
"1:p" + "34:http://example.org/omg-pic-123.bmp"+ "1:n"+ "6:Kallie"+
"1:q" + "32:secret78901234567890123456789012"+ "1:p"+ "34:http://example.org/omg-pic-123.bmp"+
"1:q"+ "32:secret78901234567890123456789012"+
"e"+
"1:<"+ "l"+
"l"+ "i0e"+ "32:").encodeToByteArray() + expHash0 + ("de"+ "e"+
"e"+
"1:="+ "d"+
"1:+" +"0:"+
"1:n" +"0:"+
"1:p" +"0:"+
"1:q" +"0:"+
"e"+ "e"+
"1:<" + "l"+
"l" + "i0e" + "32:").encodeToByteArray() + expHash0 + ("de" + "e" +
"e" +
"1:=" + "d" +
"1:n" + "0:" +
"1:p" + "0:" +
"1:q" + "0:" +
"e" +
"e").encodeToByteArray() "e").encodeToByteArray()
assertEquals(1, newSeqNo) assertEquals(1, newSeqNo)
@ -227,19 +230,20 @@ class InstrumentedTests {
// We did call push but we haven't confirmed it as stored yet, so this will still return true: // We did call push but we haven't confirmed it as stored yet, so this will still return true:
assertTrue(userProfile.needsPush()) assertTrue(userProfile.needsPush())
userProfile.confirmPushed(newSeqNo, "fakehash1")
val dump = userProfile.dump() val dump = userProfile.dump()
// (in a real client we'd now store this to disk) // (in a real client we'd now store this to disk)
assertFalse(userProfile.needsDump()) assertFalse(userProfile.needsDump())
val expectedDump = ("d" + val expectedDump = ("d" +
"1:!i2e" + "1:!"+ "i2e" +
"1:$").encodeToByteArray() + expectedPush1Decrypted.size.toString().encodeToByteArray() + "1:$").encodeToByteArray() + expectedPush1Decrypted.size.toString().encodeToByteArray() +
":".encodeToByteArray() + expectedPush1Decrypted + ":".encodeToByteArray() + expectedPush1Decrypted +
"1:(0:1:)le".encodeToByteArray()+
"e".encodeToByteArray() "e".encodeToByteArray()
assertArrayEquals(expectedDump, dump) assertArrayEquals(expectedDump, dump)
userProfile.confirmPushed(newSeqNo, "fakehash1")
val newConf = UserProfile.newInstance(edSk) val newConf = UserProfile.newInstance(edSk)
val accepted = newConf.merge("fakehash1" to newToPush) val accepted = newConf.merge("fakehash1" to newToPush)
@ -258,16 +262,16 @@ class InstrumentedTests {
val conf = userProfile.push() val conf = userProfile.push()
val conf2 = newConf.push() val conf2 = newConf.push()
userProfile.confirmPushed(conf.seqNo, "fakehash1") userProfile.confirmPushed(conf.seqNo, "fakehash2")
newConf.confirmPushed(conf2.seqNo, "fakehash2") newConf.confirmPushed(conf2.seqNo, "fakehash3")
userProfile.dump() userProfile.dump()
userProfile.dump() userProfile.dump()
assertFalse(conf.config.contentEquals(conf2.config)) assertFalse(conf.config.contentEquals(conf2.config))
newConf.merge("fakehash1" to conf.config) newConf.merge("fakehash2" to conf.config)
userProfile.merge("fakehash2" to conf2.config) userProfile.merge("fakehash3" to conf2.config)
assertTrue(newConf.needsPush()) assertTrue(newConf.needsPush())
assertTrue(userProfile.needsPush()) assertTrue(userProfile.needsPush())
@ -276,20 +280,20 @@ class InstrumentedTests {
assertEquals(3, newSeq1.seqNo) assertEquals(3, newSeq1.seqNo)
userProfile.confirmPushed(newSeq1.seqNo, "fakehash3") userProfile.confirmPushed(newSeq1.seqNo, "fakehash4")
// assume newConf push gets rejected as it was last to write and clear previous config by hash on oxenss // assume newConf push gets rejected as it was last to write and clear previous config by hash on oxenss
newConf.merge("fakehash3" to newSeq1.config) newConf.merge("fakehash4" to newSeq1.config)
val newSeqMerge = newConf.push() val newSeqMerge = newConf.push()
newConf.confirmPushed(newSeqMerge.seqNo, "fakehash4") newConf.confirmPushed(newSeqMerge.seqNo, "fakehash5")
assertEquals("Nibbler", newConf.getName()) assertEquals("Nibbler", newConf.getName())
assertEquals(4, newSeqMerge.seqNo) assertEquals(4, newSeqMerge.seqNo)
// userProfile device polls and merges // userProfile device polls and merges
userProfile.merge("fakehash4" to newSeqMerge.config) userProfile.merge("fakehash5" to newSeqMerge.config)
val userConfigMerge = userProfile.push() val userConfigMerge = userProfile.push()

View File

@ -75,4 +75,18 @@ Java_network_loki_messenger_libsession_1util_UserProfile_setPic(JNIEnv *env, job
env->ReleaseStringUTFChars(pic.first, url); env->ReleaseStringUTFChars(pic.first, url);
} }
}
extern "C"
JNIEXPORT void JNICALL
Java_network_loki_messenger_libsession_1util_UserProfile_setNtsPriority(JNIEnv *env, jobject thiz,
jint priority) {
auto profile = ptrToProfile(env, thiz);
profile->set_nts_priority(priority);
}
extern "C"
JNIEXPORT void JNICALL
Java_network_loki_messenger_libsession_1util_UserProfile_setNtsHidden(JNIEnv *env, jobject thiz,
jboolean is_hidden) {
auto profile = ptrToProfile(env, thiz);
profile->set_nts_hidden(is_hidden);
} }

View File

@ -43,11 +43,6 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
external fun free() external fun free()
@Override
fun finalize() {
free()
}
} }
class Contacts(pointer: Long) : ConfigBase(pointer) { class Contacts(pointer: Long) : ConfigBase(pointer) {
@ -98,6 +93,8 @@ class UserProfile(pointer: Long) : ConfigBase(pointer) {
external fun getName(): String? external fun getName(): String?
external fun getPic(): UserPic external fun getPic(): UserPic
external fun setPic(userPic: UserPic) external fun setPic(userPic: UserPic)
external fun setNtsPriority(priority: Int)
external fun setNtsHidden(isHidden: Boolean)
} }
class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) { class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {