1
+ package ch.pontius.swissqr.api.cli
2
+
3
+ import ch.pontius.swissqr.api.db.ListStore
4
+ import ch.pontius.swissqr.api.model.access.Access
5
+ import ch.pontius.swissqr.api.model.users.TokenId
6
+ import ch.pontius.swissqr.api.model.users.User
7
+ import com.github.ajalt.clikt.core.CliktCommand
8
+ import com.github.ajalt.clikt.core.NoOpCliktCommand
9
+ import com.github.ajalt.clikt.core.subcommands
10
+ import com.github.ajalt.clikt.parameters.options.convert
11
+ import com.github.ajalt.clikt.parameters.options.default
12
+ import com.github.ajalt.clikt.parameters.options.option
13
+ import com.github.ajalt.clikt.parameters.options.required
14
+ import com.jakewharton.picnic.Table
15
+ import com.jakewharton.picnic.table
16
+
17
+ /* *
18
+ * A collection of [CliktCommand]s to query and manipulate the [Access] logs.
19
+ *
20
+ * @author Ralph Gasser
21
+ * @version 1.0.0
22
+ */
23
+ class LogCommand (private val logStore : ListStore <Access >) : NoOpCliktCommand(name = " log" ) {
24
+
25
+ init {
26
+ this .subcommands(ListLogsCommand ())
27
+ }
28
+
29
+ /* * List of defined aliases for this [UserCommand]. */
30
+ override fun aliases (): Map <String , List <String >> {
31
+ return mapOf (
32
+ " ls" to listOf (" list" ),
33
+ " delete" to listOf (" invalidate" ),
34
+ " remove" to listOf (" invalidate" ),
35
+ " drop" to listOf (" invalidate" ),
36
+ " add" to listOf (" create" )
37
+ )
38
+ }
39
+
40
+ /* *
41
+ * Tabulates the given [Iterable] of [User] objects.
42
+ *
43
+ * @param users [Iterable] of [User] objects
44
+ * @return Resulting [Table]
45
+ */
46
+ private fun tabulateAccessLogs (users : Iterable <Access ?>): Table = table {
47
+ cellStyle {
48
+ border = true
49
+ paddingLeft = 1
50
+ paddingRight = 1
51
+ }
52
+ header {
53
+ row(" tokenId" , " source" , " path" , " method" , " status" , " timestamp" )
54
+ }
55
+ body {
56
+ users.forEach {
57
+ if (it != null ) {
58
+ row(it.tokenId, it.ip, it.path, it.method, it.status, it.timestamp)
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ /* *
65
+ * [CliktCommand] to list all available [User]s.
66
+ */
67
+ inner class ListLogsCommand : CliktCommand (name = " list" , help = " Lists all access log entries." ) {
68
+
69
+ /* * The [TokenId] to invalidate. */
70
+ private val tokenId: TokenId ? by option(" -i" , " --id" ).convert { TokenId (it) }
71
+
72
+ /* * Flag that can be set to only list active tokens. */
73
+ private val status: Int? by option(" -s" , " --status" , help = " Only lists entries that match the given status." )
74
+ .convert { it.toInt() }
75
+
76
+ /* * Flag that can be set to only list active tokens. */
77
+ private val after: Long by option(" -a" , " --after" , help = " Only lists entries that happened after the given timestamp." )
78
+ .convert { it.toLong() }
79
+ .default(Long .MIN_VALUE )
80
+
81
+ /* * Flag that can be set to only list active tokens. */
82
+ private val before: Long by option(" -b" , " --before" , help = " Only lists entries that happened before the given timestamp." )
83
+ .convert { it.toLong() }
84
+ .default(Long .MAX_VALUE )
85
+
86
+ /* * Flag that can be set to only list active tokens. */
87
+ private val limit: Int by option(" -l" , " --limit" , help = " Only lists entries that happened before the given timestamp." )
88
+ .convert { it.toInt() }
89
+ .default(100 )
90
+
91
+ override fun run () {
92
+ val logs = this @LogCommand.logStore.filter {
93
+ var match = false
94
+ if (it != null ) {
95
+ match = (it.timestamp > this .after && it.timestamp < this .before)
96
+ if (this .status != null ) {
97
+ match = match && (it.status == this .status)
98
+ }
99
+ if (this .status != null ) {
100
+ match = match && (it.status == this .status)
101
+ }
102
+ if (this .tokenId != null ) {
103
+ match = match && (it.tokenId == this .tokenId)
104
+ }
105
+ }
106
+ match
107
+ }.takeLast(this .limit)
108
+ println (this @LogCommand.tabulateAccessLogs(logs))
109
+ }
110
+ }
111
+ }
0 commit comments