Introduce the list SSH command on accounts tracking
Enable the listing of the content of the accounts tracking persistent
cache, so that the Gerrit admin can directly display and export the full
list of accounts and when they connected to Gerrit.
Change-Id: I6f5e51ca2bbd54d4d0d3b0a09ff9196a0e7c70c8
diff --git a/admin/track-and-disable-inactive-users-1.3.groovy b/admin/track-and-disable-inactive-users-1.3.groovy
index b74bdd6..99471cf 100644
--- a/admin/track-and-disable-inactive-users-1.3.groovy
+++ b/admin/track-and-disable-inactive-users-1.3.groovy
@@ -13,7 +13,9 @@
// limitations under the License.
import com.google.common.cache.*
+import com.google.gerrit.common.data.*
import com.google.common.flogger.*
+import com.google.common.util.concurrent.*
import com.google.gerrit.common.*
import com.google.gerrit.entities.*
import com.google.gerrit.extensions.annotations.*
@@ -27,6 +29,7 @@
import com.google.gerrit.server.cache.*
import com.google.gerrit.server.config.*
import com.google.gerrit.server.project.*
+import com.google.gerrit.sshd.*
import com.google.inject.*
import com.google.inject.name.*
@@ -34,6 +37,8 @@
import java.util.function.*
import java.util.stream.Collectors
+import org.kohsuke.args4j.*
+
import static java.util.concurrent.TimeUnit.*
@Singleton
@@ -267,6 +272,60 @@
}
}
+abstract class BaseSshCommand extends SshCommand {
+ void println(String msg, boolean verbose = false) {
+ if (verbose) {
+ stdout.println msg
+ }
+ stdout.flush()
+ }
+ void error(String msg) { println("[ERROR] $msg", true) }
+ void warning(String msg) { println("[WARNING] $msg", true) }
+}
+
+@CommandMetaData(name = "list", description = "List all the active accounts and their latest activity timestamp")
+@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
+class ListActiveAccountsCommand extends BaseSshCommand {
+
+ @Option(name = "--verbose", usage = "Display verbose output")
+ boolean verbose = false
+
+ @Inject
+ @Named(TrackActiveUsersCache.NAME)
+ private final Cache<Integer, Long> trackActiveUsersCache
+
+ @Inject
+ Accounts accounts
+
+ @Override
+ public void run() {
+ println("Fetching all active account ids ... ", verbose)
+ def allActiveAccountsIds = accounts.all()
+ .collect { it.account() }
+ .findAll { it.isActive() }
+ .collect { it.id().get() }
+ println("Number of active accounts fetched: ${allActiveAccountsIds.size()}", verbose)
+
+ println("AccountId | Last access [UTC] ", true)
+ println("==========|=============================", true)
+ def numTrackedActiveAccounts = 0
+ allActiveAccountsIds.each { accountId ->
+ def ts = trackActiveUsersCache.getIfPresent(accountId)
+ if (ts != null) {
+ def epochTs = MINUTES.toMillis(ts)
+ def dateTime = new Date(epochTs)
+ def dateTimeString = dateTime.format("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone('UTC'))
+ println(" $accountId | $dateTimeString", true)
+ numTrackedActiveAccounts += 1
+ } else {
+ warning("Active account id $accountId is not tracked", verbose)
+ }
+ }
+
+ println("Number of tracked active accounts: $numTrackedActiveAccounts", verbose)
+ }
+}
+
class TrackAndDisableInactiveUsersModule extends LifecycleModule {
@Override
void configure() {
@@ -279,4 +338,18 @@
}
}
-modules = [TrackAndDisableInactiveUsersModule]
+class TrackAndDisableInactiveUsersSshModule extends PluginCommandModule {
+
+ @Inject
+ TrackAndDisableInactiveUsersSshModule(@PluginName String pluginName) {
+ super(pluginName)
+ }
+
+ @Override
+ protected void configureCommands() {
+ command(ListActiveAccountsCommand.class);
+ }
+}
+
+
+modules = [TrackAndDisableInactiveUsersModule, TrackAndDisableInactiveUsersSshModule]
diff --git a/admin/track-and-disable-inactive-users.md b/admin/track-and-disable-inactive-users.md
index bcfdf66..025d5c0 100644
--- a/admin/track-and-disable-inactive-users.md
+++ b/admin/track-and-disable-inactive-users.md
@@ -62,4 +62,45 @@
```groovy_track_and_disable_inactive_users_active_users```
: Indicates the number of active users.
- A user is considered active when its inactivity period is not greater than `cache."@PLUGIN@.users_cache".maxAge` .
\ No newline at end of file
+ A user is considered active when its inactivity period is not greater than `cache."@PLUGIN@.users_cache".maxAge` .
+
+SSH commands
+---------------------
+This script exposes the following SSH commands to the Gerrit administrator:
+
+## Name
+
+`list`, list active accounts
+
+## Synopsis
+
+````
+ssh -p <port> <host> track-and-disable-inactive-users list [--verbose]
+```
+
+## Description
+
+display the list of all account-ids that are considered active and
+their last activity timestamp.
+
+The `--verbose` option produces a more detailed progress of the extraction
+of the active accounts and is intended to be used for debugging purposes.
+
+## Access
+
+Any user who has been granted the ‘Administrate Server’ capability.
+
+## Scripting
+
+This command is intended to be used in scripts and not interactively, as it
+may return a very long list of accounts and doesn't do any pagination.
+
+## Examples
+
+List all the currently active accounts.
+
+```
+$ ssh -p 29418 review.example.com track-and-disable-inactive-users list
+
+SEE ALSO
+[source] (/admin/track-and-disable-inactive-users-1.3.groovy)
\ No newline at end of file