kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Handle node public key mismatch and show warning
- Add a mismatchKey flag to Node and MessageTopBar to indicate a public key mismatch. - Set the public key to a default error value (all zeros) when a node's public key changes. - Display a warning in the MessageTopBar when a key mismatch is detected in PKC. - Only clear all nodes when a different mynode number is present.pull/1720/head
rodzic
53c240198c
commit
879a367ff5
|
@ -107,9 +107,12 @@ class NodeRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun installNodeDB(mi: MyNodeEntity, nodes: List<NodeEntity>) = withContext(dispatchers.io) {
|
suspend fun installNodeDB(mi: MyNodeEntity, nodes: List<NodeEntity>) = withContext(dispatchers.io) {
|
||||||
|
val isDifferentNode = myNodeInfo.value?.myNodeNum == mi.myNodeNum
|
||||||
nodeInfoDao.clearMyNodeInfo()
|
nodeInfoDao.clearMyNodeInfo()
|
||||||
nodeInfoDao.setMyNodeInfo(mi) // set MyNodeEntity first
|
nodeInfoDao.setMyNodeInfo(mi) // set MyNodeEntity first
|
||||||
|
if (isDifferentNode) {
|
||||||
nodeInfoDao.clearNodeInfo()
|
nodeInfoDao.clearNodeInfo()
|
||||||
|
}
|
||||||
nodeInfoDao.putAll(nodes)
|
nodeInfoDao.putAll(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package com.geeksville.mesh.database.dao
|
package com.geeksville.mesh.database.dao
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.MapColumn
|
import androidx.room.MapColumn
|
||||||
|
@ -26,10 +27,11 @@ import androidx.room.Transaction
|
||||||
import androidx.room.Upsert
|
import androidx.room.Upsert
|
||||||
import com.geeksville.mesh.database.entity.MetadataEntity
|
import com.geeksville.mesh.database.entity.MetadataEntity
|
||||||
import com.geeksville.mesh.database.entity.MyNodeEntity
|
import com.geeksville.mesh.database.entity.MyNodeEntity
|
||||||
import com.geeksville.mesh.database.entity.NodeWithRelations
|
|
||||||
import com.geeksville.mesh.database.entity.NodeEntity
|
import com.geeksville.mesh.database.entity.NodeEntity
|
||||||
|
import com.geeksville.mesh.database.entity.NodeWithRelations
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
private const val TAG = "NodeInfoDao"
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
@Dao
|
@Dao
|
||||||
interface NodeInfoDao {
|
interface NodeInfoDao {
|
||||||
|
@ -108,8 +110,22 @@ interface NodeInfoDao {
|
||||||
@Upsert
|
@Upsert
|
||||||
fun upsert(node: NodeEntity)
|
fun upsert(node: NodeEntity)
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Transaction
|
||||||
fun putAll(nodes: List<NodeEntity>)
|
fun putAll(nodes: List<NodeEntity>) {
|
||||||
|
val existingNodes = nodes.mapNotNull {
|
||||||
|
getNodeByNum(it.num)
|
||||||
|
}
|
||||||
|
nodes.forEach { newNode ->
|
||||||
|
val existingNode = existingNodes.firstOrNull { it.num == newNode.num }
|
||||||
|
if (existingNode != null && existingNode.user.publicKey != newNode.user.publicKey) {
|
||||||
|
Log.w(TAG, "Node ${newNode.num} has changed its public key")
|
||||||
|
val user =
|
||||||
|
newNode.user.toBuilder().setPublicKey(NodeEntity.ERROR_BYTE_STRING).build()
|
||||||
|
newNode.user = user
|
||||||
|
}
|
||||||
|
upsert(newNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Query("DELETE FROM nodes")
|
@Query("DELETE FROM nodes")
|
||||||
fun clearNodeInfo()
|
fun clearNodeInfo()
|
||||||
|
@ -122,4 +138,7 @@ interface NodeInfoDao {
|
||||||
|
|
||||||
@Query("DELETE FROM metadata WHERE num=:num")
|
@Query("DELETE FROM metadata WHERE num=:num")
|
||||||
fun deleteMetadata(num: Int)
|
fun deleteMetadata(num: Int)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM nodes WHERE num = :num")
|
||||||
|
fun getNodeByNum(num: Int): NodeEntity?
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ data class NodeEntity(
|
||||||
|
|
||||||
val isUnknownUser get() = user.hwModel == MeshProtos.HardwareModel.UNSET
|
val isUnknownUser get() = user.hwModel == MeshProtos.HardwareModel.UNSET
|
||||||
val hasPKC get() = !user.publicKey.isEmpty
|
val hasPKC get() = !user.publicKey.isEmpty
|
||||||
val errorByteString: ByteString get() = ByteString.copyFrom(ByteArray(32) { 0 })
|
val errorByteString: ByteString get() = ERROR_BYTE_STRING
|
||||||
|
|
||||||
fun setPosition(p: MeshProtos.Position, defaultTime: Int = currentTime()) {
|
fun setPosition(p: MeshProtos.Position, defaultTime: Int = currentTime()) {
|
||||||
position = p.copy { time = if (p.time != 0) p.time else defaultTime }
|
position = p.copy { time = if (p.time != 0) p.time else defaultTime }
|
||||||
|
@ -174,6 +174,7 @@ data class NodeEntity(
|
||||||
fun degD(i: Int) = i * 1e-7
|
fun degD(i: Int) = i * 1e-7
|
||||||
fun degI(d: Double) = (d * 1e7).toInt()
|
fun degI(d: Double) = (d * 1e7).toInt()
|
||||||
|
|
||||||
|
val ERROR_BYTE_STRING: ByteString = ByteString.copyFrom(ByteArray(32) { 0 })
|
||||||
fun currentTime() = (System.currentTimeMillis() / 1000).toInt()
|
fun currentTime() = (System.currentTimeMillis() / 1000).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ import com.geeksville.mesh.PaxcountProtos
|
||||||
import com.geeksville.mesh.TelemetryProtos.DeviceMetrics
|
import com.geeksville.mesh.TelemetryProtos.DeviceMetrics
|
||||||
import com.geeksville.mesh.TelemetryProtos.EnvironmentMetrics
|
import com.geeksville.mesh.TelemetryProtos.EnvironmentMetrics
|
||||||
import com.geeksville.mesh.TelemetryProtos.PowerMetrics
|
import com.geeksville.mesh.TelemetryProtos.PowerMetrics
|
||||||
|
import com.geeksville.mesh.database.entity.NodeEntity
|
||||||
import com.geeksville.mesh.util.GPSFormat
|
import com.geeksville.mesh.util.GPSFormat
|
||||||
import com.geeksville.mesh.util.latLongToMeter
|
import com.geeksville.mesh.util.latLongToMeter
|
||||||
import com.geeksville.mesh.util.toDistanceString
|
import com.geeksville.mesh.util.toDistanceString
|
||||||
import com.google.protobuf.ByteString
|
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
data class Node(
|
data class Node(
|
||||||
|
@ -59,8 +59,7 @@ data class Node(
|
||||||
|
|
||||||
val isUnknownUser get() = user.hwModel == MeshProtos.HardwareModel.UNSET
|
val isUnknownUser get() = user.hwModel == MeshProtos.HardwareModel.UNSET
|
||||||
val hasPKC get() = !user.publicKey.isEmpty
|
val hasPKC get() = !user.publicKey.isEmpty
|
||||||
val errorByteString: ByteString get() = ByteString.copyFrom(ByteArray(32) { 0 })
|
val mismatchKey get() = user.publicKey == NodeEntity.ERROR_BYTE_STRING
|
||||||
val mismatchKey get() = user.publicKey == errorByteString
|
|
||||||
|
|
||||||
val hasEnvironmentMetrics: Boolean
|
val hasEnvironmentMetrics: Boolean
|
||||||
get() = environmentMetrics != EnvironmentMetrics.getDefaultInstance()
|
get() = environmentMetrics != EnvironmentMetrics.getDefaultInstance()
|
||||||
|
|
|
@ -184,6 +184,8 @@ internal fun MessageScreen(
|
||||||
DataPacket.ID_BROADCAST -> channelName
|
DataPacket.ID_BROADCAST -> channelName
|
||||||
else -> viewModel.getUser(nodeId).longName
|
else -> viewModel.getUser(nodeId).longName
|
||||||
}
|
}
|
||||||
|
val mismatchKey =
|
||||||
|
DataPacket.PKC_CHANNEL_INDEX == channelIndex && viewModel.getNode(nodeId).mismatchKey
|
||||||
|
|
||||||
// if (channelIndex != DataPacket.PKC_CHANNEL_INDEX && nodeId != DataPacket.ID_BROADCAST) {
|
// if (channelIndex != DataPacket.PKC_CHANNEL_INDEX && nodeId != DataPacket.ID_BROADCAST) {
|
||||||
// subtitle = "(ch: $channelIndex - $channelName)"
|
// subtitle = "(ch: $channelIndex - $channelName)"
|
||||||
|
@ -242,7 +244,7 @@ internal fun MessageScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MessageTopBar(title, channelIndex, onNavigateBack)
|
MessageTopBar(title, channelIndex, mismatchKey, onNavigateBack)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
|
@ -368,6 +370,7 @@ private fun ActionModeTopBar(
|
||||||
private fun MessageTopBar(
|
private fun MessageTopBar(
|
||||||
title: String,
|
title: String,
|
||||||
channelIndex: Int?,
|
channelIndex: Int?,
|
||||||
|
mismatchKey: Boolean = false,
|
||||||
onNavigateBack: () -> Unit
|
onNavigateBack: () -> Unit
|
||||||
) = TopAppBar(
|
) = TopAppBar(
|
||||||
title = { Text(text = title) },
|
title = { Text(text = title) },
|
||||||
|
@ -381,7 +384,7 @@ private fun MessageTopBar(
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
if (channelIndex == DataPacket.PKC_CHANNEL_INDEX) {
|
if (channelIndex == DataPacket.PKC_CHANNEL_INDEX) {
|
||||||
NodeKeyStatusIcon(hasPKC = true, mismatchKey = false)
|
NodeKeyStatusIcon(hasPKC = true, mismatchKey = mismatchKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Ładowanie…
Reference in New Issue