Add Storage Service plugin to Spinner.

fork-5.53.8
Cody Henthorne 2022-06-24 11:07:37 -04:00
rodzic 9bc25132c3
commit 89a6730efe
13 zmienionych plików z 162 dodań i 9 usunięć

Wyświetl plik

@ -69,6 +69,9 @@ class SpinnerApplicationContext : ApplicationContext() {
"megaphones" to DatabaseConfig(db = MegaphoneDatabase.getInstance(this).sqlCipherDatabase),
"localmetrics" to DatabaseConfig(db = LocalMetricsDatabase.getInstance(this).sqlCipherDatabase),
"logs" to DatabaseConfig(db = LogDatabase.getInstance(this).sqlCipherDatabase),
),
linkedMapOf(
StorageServicePlugin.PATH to StorageServicePlugin()
)
)

Wyświetl plik

@ -0,0 +1,58 @@
package org.thoughtcrime.securesms
import org.signal.spinner.Plugin
import org.signal.spinner.PluginResult
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore
class StorageServicePlugin : Plugin {
override val name: String = "Storage"
override val path: String = PATH
override fun get(): PluginResult {
val columns = listOf("Type", "Data")
val rows = mutableListOf<List<String>>()
val manager = ApplicationDependencies.getSignalServiceAccountManager()
val storageServiceKey = SignalStore.storageService().orCreateStorageKey
val storageManifestVersion = manager.storageManifestVersion
val manifest = manager.getStorageManifestIfDifferentVersion(storageServiceKey, storageManifestVersion - 1).get()
val signalStorageRecords = manager.readStorageRecords(storageServiceKey, manifest.storageIds)
for (record in signalStorageRecords) {
val row = mutableListOf<String>()
if (record.account.isPresent) {
row += "Account"
row += record.account.get().toProto().toString()
} else if (record.contact.isPresent) {
row += "Contact"
row += record.contact.get().toProto().toString()
} else if (record.groupV1.isPresent) {
row += "GV1"
row += record.groupV1.get().toProto().toString()
} else if (record.groupV2.isPresent) {
row += "GV2"
row += record.groupV2.get().toProto().toString()
} else if (record.storyDistributionList.isPresent) {
row += "Distribution List"
row += record.storyDistributionList.get().toProto().toString()
} else {
row += "Unknown"
row += ""
}
rows += row
}
rows.sortBy { it.first() }
return PluginResult.TableResult(
columns = columns,
rows = rows
)
}
companion object {
const val PATH = "/storage"
}
}

Wyświetl plik

@ -268,7 +268,7 @@ public final class SignalAccountRecord implements SignalRecord {
return proto.getSubscriptionManuallyCancelled();
}
AccountRecord toProto() {
public AccountRecord toProto() {
return proto;
}

Wyświetl plik

@ -191,7 +191,7 @@ public final class SignalContactRecord implements SignalRecord {
return proto.getHideStory();
}
ContactRecord toProto() {
public ContactRecord toProto() {
return proto;
}

Wyświetl plik

@ -114,7 +114,7 @@ public final class SignalGroupV1Record implements SignalRecord {
return proto.getMutedUntilTimestamp();
}
GroupV1Record toProto() {
public GroupV1Record toProto() {
return proto;
}

Wyświetl plik

@ -140,7 +140,7 @@ public final class SignalGroupV2Record implements SignalRecord {
return proto.getHideStory();
}
GroupV2Record toProto() {
public GroupV2Record toProto() {
return proto;
}

Wyświetl plik

@ -23,7 +23,8 @@ class MainActivity : AppCompatActivity() {
"Name" to "${Build.MODEL} (API ${Build.VERSION.SDK_INT})",
"Package" to packageName
),
mapOf("main" to Spinner.DatabaseConfig(db = db))
mapOf("main" to Spinner.DatabaseConfig(db = db)),
emptyMap()
)
}

Wyświetl plik

@ -23,4 +23,7 @@
<li {{#if isBrowse}}class="active"{{/if}}><a href="/browse?db={{database}}">Browse</a></li>
<li {{#if isQuery}}class="active"{{/if}}><a href="/query?db={{database}}">Query</a></li>
<li {{#if isRecent}}class="active"{{/if}}><a href="/recent?db={{database}}">Recent</a></li>
{{#each plugins}}
<li {{#if (eq name activePlugin.name)}}class="active"{{/if}}><a href="{{path}}">{{name}}</a></li>
{{/each}}
</ol>

Wyświetl plik

@ -0,0 +1,28 @@
<html>
{{> partials/head title=activePlugin.name }}
<body>
{{> partials/prefix}}
{{#if (eq "table" pluginResult.type)}}
<h1>Data</h1>
{{pluginResult.rowCount}} row(s). <br />
<br />
<table>
<tr>
{{#each pluginResult.columns}}
<th>{{this}}</th>
{{/each}}
</tr>
{{#each pluginResult.rows}}
<tr>
{{#each this}}
<td><pre>{{{this}}}</pre></td>
{{/each}}
</tr>
{{/each}}
</table>
{{/if}}
{{> partials/suffix }}
</body>
</html>

Wyświetl plik

@ -0,0 +1,7 @@
package org.signal.spinner
interface Plugin {
fun get(): PluginResult
val name: String
val path: String
}

Wyświetl plik

@ -0,0 +1,9 @@
package org.signal.spinner
sealed class PluginResult(val type: String) {
data class TableResult(
val columns: List<String>,
val rows: List<List<String>>,
val rowCount: Int = rows.size,
) : PluginResult("table")
}

Wyświetl plik

@ -18,9 +18,9 @@ object Spinner {
private lateinit var server: SpinnerServer
fun init(application: Application, deviceInfo: Map<String, String>, databases: Map<String, DatabaseConfig>) {
fun init(application: Application, deviceInfo: Map<String, String>, databases: Map<String, DatabaseConfig>, plugins: Map<String, Plugin>) {
try {
server = SpinnerServer(application, deviceInfo, databases)
server = SpinnerServer(application, deviceInfo, databases, plugins)
server.start()
} catch (e: IOException) {
Log.w(TAG, "Spinner server hit IO exception!", e)

Wyświetl plik

@ -29,7 +29,8 @@ import kotlin.math.min
internal class SpinnerServer(
private val application: Application,
deviceInfo: Map<String, String>,
private val databases: Map<String, DatabaseConfig>
private val databases: Map<String, DatabaseConfig>,
private val plugins: Map<String, Plugin>
) : NanoHTTPD(5000) {
companion object {
@ -66,7 +67,14 @@ internal class SpinnerServer(
session.method == Method.GET && session.uri == "/query" -> getQuery(dbParam, dbConfig.db)
session.method == Method.POST && session.uri == "/query" -> postQuery(dbParam, dbConfig, session)
session.method == Method.GET && session.uri == "/recent" -> getRecent(dbParam, dbConfig.db)
else -> newFixedLengthResponse(Response.Status.NOT_FOUND, MIME_HTML, "Not found")
else -> {
val plugin = plugins[session.uri]
if (plugin != null && session.method == Method.GET) {
getPlugin(dbParam, plugin)
} else {
newFixedLengthResponse(Response.Status.NOT_FOUND, MIME_HTML, "Not found")
}
}
}
} catch (t: Throwable) {
Log.e(TAG, t)
@ -93,6 +101,7 @@ internal class SpinnerServer(
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
tables = db.getTables().toTableInfo(),
indices = db.getIndexes().toIndexInfo(),
triggers = db.getTriggers().toTriggerInfo(),
@ -109,6 +118,7 @@ internal class SpinnerServer(
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
tableNames = db.getTableNames()
)
)
@ -140,6 +150,7 @@ internal class SpinnerServer(
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
tableNames = dbConfig.db.getTableNames(),
table = table,
queryResult = queryResult,
@ -163,6 +174,7 @@ internal class SpinnerServer(
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
query = ""
)
)
@ -184,6 +196,7 @@ internal class SpinnerServer(
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
recentSql = queries?.reversed()
)
)
@ -202,12 +215,28 @@ internal class SpinnerServer(
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
query = rawQuery,
queryResult = dbConfig.db.query(query).toQueryResult(queryStartTime = startTime, columnTransformers = dbConfig.columnTransformers)
)
)
}
private fun getPlugin(dbName: String, plugin: Plugin): Response {
return renderTemplate(
"plugin",
PluginPageModel(
environment = environment,
deviceInfo = deviceInfo,
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
activePlugin = plugin,
pluginResult = plugin.get()
)
)
}
private fun internalError(throwable: Throwable): Response {
val stackTrace = ExceptionUtil.convertThrowableToString(throwable)
.split("\n")
@ -361,6 +390,7 @@ internal class SpinnerServer(
val deviceInfo: Map<String, String>
val database: String
val databases: List<String>
val plugins: List<Plugin>
}
data class OverviewPageModel(
@ -368,6 +398,7 @@ internal class SpinnerServer(
override val deviceInfo: Map<String, String>,
override val database: String,
override val databases: List<String>,
override val plugins: List<Plugin>,
val tables: List<TableInfo>,
val indices: List<IndexInfo>,
val triggers: List<TriggerInfo>,
@ -379,6 +410,7 @@ internal class SpinnerServer(
override val deviceInfo: Map<String, String>,
override val database: String,
override val databases: List<String>,
override val plugins: List<Plugin>,
val tableNames: List<String>,
val table: String? = null,
val queryResult: QueryResult? = null,
@ -390,6 +422,7 @@ internal class SpinnerServer(
override val deviceInfo: Map<String, String>,
override val database: String,
override val databases: List<String>,
override val plugins: List<Plugin>,
val query: String = "",
val queryResult: QueryResult? = null
) : PrefixPageData
@ -399,9 +432,20 @@ internal class SpinnerServer(
override val deviceInfo: Map<String, String>,
override val database: String,
override val databases: List<String>,
override val plugins: List<Plugin>,
val recentSql: List<RecentQuery>?
) : PrefixPageData
data class PluginPageModel(
override val environment: String,
override val deviceInfo: Map<String, String>,
override val database: String,
override val databases: List<String>,
override val plugins: List<Plugin>,
val activePlugin: Plugin,
val pluginResult: PluginResult
) : PrefixPageData
data class QueryResult(
val columns: List<String>,
val rows: List<List<String>>,