kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add Storage Service plugin to Spinner.
rodzic
9bc25132c3
commit
89a6730efe
|
@ -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()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -268,7 +268,7 @@ public final class SignalAccountRecord implements SignalRecord {
|
|||
return proto.getSubscriptionManuallyCancelled();
|
||||
}
|
||||
|
||||
AccountRecord toProto() {
|
||||
public AccountRecord toProto() {
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ public final class SignalContactRecord implements SignalRecord {
|
|||
return proto.getHideStory();
|
||||
}
|
||||
|
||||
ContactRecord toProto() {
|
||||
public ContactRecord toProto() {
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ public final class SignalGroupV1Record implements SignalRecord {
|
|||
return proto.getMutedUntilTimestamp();
|
||||
}
|
||||
|
||||
GroupV1Record toProto() {
|
||||
public GroupV1Record toProto() {
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ public final class SignalGroupV2Record implements SignalRecord {
|
|||
return proto.getHideStory();
|
||||
}
|
||||
|
||||
GroupV2Record toProto() {
|
||||
public GroupV2Record toProto() {
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,7 @@
|
|||
package org.signal.spinner
|
||||
|
||||
interface Plugin {
|
||||
fun get(): PluginResult
|
||||
val name: String
|
||||
val path: String
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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>>,
|
||||
|
|
Ładowanie…
Reference in New Issue