Adds new tile on the admin home page with system data. (#301)

* Adds new tile on the admin home page with system data. Also fixes the active users bug in the pie chart

* Fixes missing parentheses

* Updates user stats cache when signing in

* Reads active number of users from session provider

* Removes unused variable

* Small improvements

* Removes acl properties from system data websocket and performs initial push of data

* fix: remove acl fetch

---------

Co-authored-by: DecDuck <declanahofmeyr@gmail.com>
This commit is contained in:
Paco
2026-01-21 23:58:21 +00:00
committed by GitHub
parent 82cdc1e1aa
commit d8db5b5b85
18 changed files with 243 additions and 23 deletions
+5
View File
@@ -23,6 +23,11 @@ export default function createCacheSessionProvider() {
const session = await sessions.get(token);
return session ? (session as T) : undefined; // Ensure undefined is returned if session is not found
},
async getNumberActiveSessions() {
const now = new Date();
const allSessions = await sessions.getItems(await sessions.getKeys());
return allSessions.filter(({ value }) => value.expiresAt > now).length;
},
async updateSession(token, data) {
return (await this.setSession(token, data)) !== undefined;
},
+16
View File
@@ -1,3 +1,5 @@
import { DateTime } from "luxon";
import prisma from "../db/database";
import type { SessionProvider, SessionWithToken } from "./types";
import cacheHandler from "../cache";
@@ -76,6 +78,20 @@ export default function createDBSessionHandler(): SessionProvider {
},
});
},
async getNumberActiveSessions() {
return (
(
await prisma.session.groupBy({
by: ["userId"],
where: {
expiresAt: {
gt: DateTime.now().toJSDate(),
},
},
})
).length || 0
);
},
async findSessions(options) {
const search: SessionWhereInput[] = [];
if (options.userId) {
+8 -2
View File
@@ -10,8 +10,10 @@ import { parse as parseCookies } from "cookie-es";
import type { MinimumRequestObject } from "~/server/h3";
import type { DurationLike } from "luxon";
import { DateTime } from "luxon";
import createDBSessionHandler from "./db";
import prisma from "../db/database";
// import createMemorySessionHandler from "./memory";
import createDBSessionHandler from "./db";
// import createCacheSessionProvider from "./cache";
/*
This implementation may need work.
@@ -49,7 +51,7 @@ export class SessionHandler {
// Create a new provider
// this.sessionProvider = createCacheSessionProvider();
this.sessionProvider = createDBSessionHandler();
// this.sessionProvider = createMemorySessionProvider();
// this.sessionProvider = createMemorySessionHandler();
}
async signin(
@@ -217,6 +219,10 @@ export class SessionHandler {
return await this.sessionProvider.findSessions(terms);
}
async getNumberActiveSessions() {
return this.sessionProvider.getNumberActiveSessions();
}
/**
* Update session info
* @param token session token
+9
View File
@@ -22,6 +22,15 @@ export default function createMemorySessionHandler() {
sessions.delete(token);
return true;
},
async getNumberActiveSessions() {
let activeSessions = 0;
for (const [_key, session] of sessions) {
if (session.expiresAt.getDate() > Date.now()) {
activeSessions += 1;
}
}
return activeSessions;
},
async cleanupSessions() {
const now = new Date();
for (const [token, session] of sessions) {
+1
View File
@@ -50,4 +50,5 @@ export interface SessionProvider {
removeSession: (token: string) => Promise<boolean>;
cleanupSessions: () => Promise<void>;
findSessions: (options: SessionSearchTerms) => Promise<SessionWithToken[]>;
getNumberActiveSessions: () => Promise<number>;
}