fix(conifg): implement `sessionPasskey` handling for admin requests (#1263)

pull/1266/head
Andre K 2024-09-20 06:07:35 -03:00 zatwierdzone przez GitHub
rodzic 16b822cec4
commit 36a13d7687
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
4 zmienionych plików z 68 dodań i 29 usunięć

Wyświetl plik

@ -16,12 +16,14 @@ import com.geeksville.mesh.MyNodeInfo
import com.geeksville.mesh.NodeInfo
import com.geeksville.mesh.Portnums
import com.geeksville.mesh.Position
import com.geeksville.mesh.R
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.config
import com.geeksville.mesh.database.entity.toNodeInfo
import com.geeksville.mesh.deviceProfile
import com.geeksville.mesh.moduleConfig
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
import com.geeksville.mesh.ui.AdminRoute
import com.geeksville.mesh.ui.ConfigRoute
import com.geeksville.mesh.ui.ResponseState
import com.google.protobuf.MessageLite
@ -44,6 +46,7 @@ import javax.inject.Inject
*/
data class RadioConfigState(
val route: String = "",
val metadata: MeshProtos.DeviceMetadata = MeshProtos.DeviceMetadata.getDefaultInstance(),
val userConfig: MeshProtos.User = MeshProtos.User.getDefaultInstance(),
val channelList: List<ChannelProtos.ChannelSettings> = emptyList(),
val radioConfig: ConfigProtos.Config = config {},
@ -51,7 +54,9 @@ data class RadioConfigState(
val ringtone: String = "",
val cannedMessageMessages: String = "",
val responseState: ResponseState<Boolean> = ResponseState.Empty,
)
) {
fun hasMetadata() = metadata != MeshProtos.DeviceMetadata.getDefaultInstance()
}
@HiltViewModel
class RadioConfigViewModel @Inject constructor(
@ -247,30 +252,55 @@ class RadioConfigViewModel @Inject constructor(
"Request getCannedMessages error"
)
fun requestShutdown(destNum: Int) = request(
private fun requestShutdown(destNum: Int) = request(
destNum,
{ service, packetId, dest -> service.requestShutdown(packetId, dest) },
"Request shutdown error"
)
fun requestReboot(destNum: Int) = request(
private fun requestReboot(destNum: Int) = request(
destNum,
{ service, packetId, dest -> service.requestReboot(packetId, dest) },
"Request reboot error"
)
fun requestFactoryReset(destNum: Int) = request(
private fun requestFactoryReset(destNum: Int) = request(
destNum,
{ service, packetId, dest -> service.requestFactoryReset(packetId, dest) },
"Request factory reset error"
)
fun requestNodedbReset(destNum: Int) = request(
private fun requestNodedbReset(destNum: Int) = request(
destNum,
{ service, packetId, dest -> service.requestNodedbReset(packetId, dest) },
"Request NodeDB reset error"
)
private fun sendAdminRequest(destNum: Int) {
when (radioConfigState.value.route) {
AdminRoute.REBOOT.name -> requestReboot(destNum)
AdminRoute.SHUTDOWN.name -> with(radioConfigState.value) {
if (hasMetadata() && !metadata.canShutdown) {
setResponseStateError(app.getString(R.string.cant_shutdown))
} else {
requestShutdown(destNum)
}
}
AdminRoute.FACTORY_RESET.name -> requestFactoryReset(destNum)
AdminRoute.NODEDB_RESET.name -> requestNodedbReset(destNum)
}
}
fun getSessionPasskey(destNum: Int) {
if (radioConfigState.value.hasMetadata()) {
sendAdminRequest(destNum)
} else {
getConfig(destNum, AdminProtos.AdminMessage.ConfigType.SESSIONKEY_CONFIG_VALUE)
setResponseStateTotal(2)
}
}
fun setFixedPosition(destNum: Int, position: Position) {
try {
meshService?.setFixedPosition(destNum, position)
@ -444,9 +474,12 @@ class RadioConfigViewModel @Inject constructor(
setResponseStateError("Unexpected sender: ${packet.from.toUInt()} instead of ${destNum.toUInt()}.")
return
}
// check if destination is channel editor
val goChannels = route == ConfigRoute.CHANNELS.name
when (parsed.payloadVariantCase) {
AdminProtos.AdminMessage.PayloadVariantCase.GET_DEVICE_METADATA_RESPONSE -> {
_radioConfigState.update { it.copy(metadata = parsed.getDeviceMetadataResponse) }
incrementCompleted()
}
AdminProtos.AdminMessage.PayloadVariantCase.GET_CHANNEL_RESPONSE -> {
val response = parsed.getChannelResponse
// Stop once we get to the first disabled entry
@ -457,7 +490,7 @@ class RadioConfigViewModel @Inject constructor(
})
}
incrementCompleted()
if (response.index + 1 < maxChannels && goChannels) {
if (response.index + 1 < maxChannels && route == ConfigRoute.CHANNELS.name) {
// Not done yet, request next channel
getChannel(destNum, response.index + 1)
}
@ -504,6 +537,10 @@ class RadioConfigViewModel @Inject constructor(
else -> TODO()
}
if (AdminRoute.entries.any { it.name == route }) {
sendAdminRequest(destNum)
}
requestIds.update { it.apply { remove(data.requestId) } }
}
}

Wyświetl plik

@ -1794,7 +1794,11 @@ class MeshService : Service(), Logging {
override fun getRemoteConfig(id: Int, destNum: Int, config: Int) = toRemoteExceptions {
sendToRadio(newMeshPacketTo(destNum).buildAdminPacket(id = id, wantResponse = true) {
getConfigRequestValue = config
if (config == AdminProtos.AdminMessage.ConfigType.SESSIONKEY_CONFIG_VALUE) {
getDeviceMetadataRequest = true
} else {
getConfigRequestValue = config
}
})
}

Wyświetl plik

@ -163,6 +163,14 @@ class DeviceSettingsFragment : ScreenFragment("Radio Configuration"), Logging {
}
}
enum class AdminRoute(@StringRes val title: Int) {
REBOOT(R.string.reboot),
SHUTDOWN(R.string.shutdown),
FACTORY_RESET(R.string.factory_reset),
NODEDB_RESET(R.string.nodedb_reset),
;
}
// Config (configType = AdminProtos.AdminMessage.ConfigType)
enum class ConfigRoute(val title: String, val configType: Int = 0) {
USER("User"),
@ -197,6 +205,7 @@ enum class ModuleRoute(val title: String, val configType: Int = 0) {
}
private fun getName(route: Any): String = when (route) {
is AdminRoute -> route.name
is ConfigRoute -> route.name
is ModuleRoute -> route.name
else -> ""
@ -304,8 +313,11 @@ fun RadioConfigNavHost(
},
onComplete = {
val route = radioConfigState.route
if (route.isNotEmpty()) navController.navigate(route)
viewModel.clearPacketResponse()
if (ConfigRoute.entries.any { it.name == route } ||
ModuleRoute.entries.any { it.name == route }) {
navController.navigate(route)
viewModel.clearPacketResponse()
}
}
)
@ -346,20 +358,8 @@ fun RadioConfigNavHost(
showEditDeviceProfileDialog = true
}
"REBOOT" -> {
viewModel.requestReboot(destNum)
}
"SHUTDOWN" -> {
viewModel.requestShutdown(destNum)
}
"FACTORY_RESET" -> {
viewModel.requestFactoryReset(destNum)
}
"NODEDB_RESET" -> {
viewModel.requestNodedbReset(destNum)
is AdminRoute -> {
viewModel.getSessionPasskey(destNum)
}
is ConfigRoute -> {
@ -753,10 +753,7 @@ private fun RadioSettingsScreen(
item { NavCard("Export configuration", enabled = enabled) { onRouteClick("EXPORT") } }
}
item { NavButton(R.string.reboot, enabled) { onRouteClick("REBOOT") } }
item { NavButton(R.string.shutdown, enabled) { onRouteClick("SHUTDOWN") } }
item { NavButton(R.string.factory_reset, enabled) { onRouteClick("FACTORY_RESET") } }
item { NavButton(R.string.nodedb_reset, enabled) { onRouteClick("NODEDB_RESET") } }
items(AdminRoute.entries) { NavButton(it.title, enabled) { onRouteClick(it) } }
}
}

Wyświetl plik

@ -148,6 +148,7 @@
<string name="preferences_system_default">System default</string>
<string name="resend">Resend</string>
<string name="shutdown">Shutdown</string>
<string name="cant_shutdown">Shutdown not supported on this device</string>
<string name="reboot">Reboot</string>
<string name="traceroute">Traceroute</string>
<string name="intro_show">Show Introduction</string>