diff --git a/lib/SessionStatistics.php b/lib/SessionStatistics.php
index fa246cbfe..b5f305b76 100644
--- a/lib/SessionStatistics.php
+++ b/lib/SessionStatistics.php
@@ -49,15 +49,23 @@ public function getSessionStatistics(): array {
'last3months' => $this->getNumberOfActiveUsers(self::OFFSET_3MONTHS),
'last6months' => $this->getNumberOfActiveUsers(self::OFFSET_6MONTHS),
'lastyear' => $this->getNumberOfActiveUsers(self::OFFSET_1YEAR),
+ 'total' => $this->getNumberOfUsersLoggedInSince(1),
];
}
/**
- * get number of active user in a given time span
+ * Get number of active user in a given time span
*
* @param int $offset seconds
*/
private function getNumberOfActiveUsers(int $offset): int {
+ return $this->getNumberOfUsersLoggedInSince($this->timeFactory->getTime() - $offset);
+ }
+
+ /**
+ * Get number of users whose last login is at or after the given timestamp
+ */
+ private function getNumberOfUsersLoggedInSince(int $timestamp): int {
$queryBuilder = $this->connection->getQueryBuilder();
$queryBuilder->select($queryBuilder->func()->count('userid'))
->from('preferences')
@@ -65,7 +73,7 @@ private function getNumberOfActiveUsers(int $offset): int {
->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('lastLogin')))
->andwhere($queryBuilder->expr()->gte(
$queryBuilder->expr()->castColumn('configvalue', IQueryBuilder::PARAM_INT),
- $queryBuilder->createNamedParameter($this->timeFactory->getTime() - $offset, IQueryBuilder::PARAM_INT),
+ $queryBuilder->createNamedParameter($timestamp, IQueryBuilder::PARAM_INT),
IQueryBuilder::PARAM_INT,
));
diff --git a/src/components/ActiveUsersSection.vue b/src/components/ActiveUsersSection.vue
index 32eed219c..bac0b4572 100644
--- a/src/components/ActiveUsersSection.vue
+++ b/src/components/ActiveUsersSection.vue
@@ -27,6 +27,11 @@
{{ activeUsers.last1month }}
{{ percentageOfAllUsers(activeUsers.last1month) }}
+
+ {{ t('serverinfo', 'Logged in at least once') }}
+ {{ activeUsers.total }}
+ {{ percentageOfAllUsers(activeUsers.total) }}
+
@@ -38,7 +43,7 @@ import AccountGroup from 'vue-material-design-icons/AccountGroup.vue'
import SectionHeading from './SectionHeading.vue'
const props = defineProps<{
- activeUsers: { last1hour: number, last24hours: number, last7days: number, last1month: number }
+ activeUsers: { last1hour: number, last24hours: number, last7days: number, last1month: number, total: number }
numUsers: number
}>()
diff --git a/src/composables/useStaticData.ts b/src/composables/useStaticData.ts
index c8e936165..30fedd5fc 100644
--- a/src/composables/useStaticData.ts
+++ b/src/composables/useStaticData.ts
@@ -49,7 +49,7 @@ export interface StaticData {
opcache: OpcacheStatus
fpm: Record | false
database: { type: string, version: string, size: number }
- activeUsers: { last1hour: number, last24hours: number, last7days: number, last1month: number }
+ activeUsers: { last1hour: number, last24hours: number, last7days: number, last1month: number, total: number }
freeSpace: number | null
memTotal: number
phpinfo: boolean
diff --git a/tests/lib/SessionStatisticsTest.php b/tests/lib/SessionStatisticsTest.php
index 279b9c8d2..fd97ce5cb 100644
--- a/tests/lib/SessionStatisticsTest.php
+++ b/tests/lib/SessionStatisticsTest.php
@@ -104,7 +104,7 @@ public function testGetSessionStatistics() {
$result = $this->instance->getSessionStatistics();
- $this->assertSame(8, count($result));
+ $this->assertSame(9, count($result));
$this->assertSame(2, $result['last5minutes']); // 2 users in last 5 minutes
$this->assertSame(5, $result['last1hour']); // 2 + 3 users in last hour
$this->assertSame(6, $result['last24hours']); // 2 + 3 + 1 users in last day
@@ -113,5 +113,6 @@ public function testGetSessionStatistics() {
$this->assertSame(8, $result['last3months']); // 2 + 3 + 1 + 0 + 1 + 1 users in last 3 months
$this->assertSame(9, $result['last6months']); // 2 + 3 + 1 + 0 + 1 + 1 + 1 users in last 6 months
$this->assertSame(12, $result['lastyear']); // 2 + 3 + 1 + 0 + 1 + 1 + 1 + 3 users in last year
+ $this->assertGreaterThanOrEqual(12, $result['total']); // all 12 users, plus any existing lastLogin values in the database
}
}