feat: add last_seen tracking for users
Adds last_seen field to track when users last accessed the tool: - Add lastSeen column to users table schema (nullable timestamp) - Create migration to add last_seen column to existing databases - Add updateLastSeen() function to auth.service.js - Update auth derive middleware to update last_seen on each authenticated request (async, non-blocking) - Add lastSeen to admin getUserStats() query for display in admin users table - Add "Last Seen" column to admin users table in frontend Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -127,6 +127,7 @@ export async function getUserStats() {
|
||||
email: users.email,
|
||||
callsign: users.callsign,
|
||||
isAdmin: users.isAdmin,
|
||||
lastSeen: users.lastSeen,
|
||||
qsoCount: sql`CAST(COUNT(${qsos.id}) AS INTEGER)`,
|
||||
lotwConfirmed: sql`CAST(SUM(CASE WHEN ${qsos.lotwQslRstatus} = 'Y' THEN 1 ELSE 0 END) AS INTEGER)`,
|
||||
dclConfirmed: sql`CAST(SUM(CASE WHEN ${qsos.dclQslRstatus} = 'Y' THEN 1 ELSE 0 END) AS INTEGER)`,
|
||||
@@ -144,10 +145,13 @@ export async function getUserStats() {
|
||||
.groupBy(users.id)
|
||||
.orderBy(sql`COUNT(${qsos.id}) DESC`);
|
||||
|
||||
// Convert lastSync timestamps (seconds) to Date objects for JSON serialization
|
||||
// Convert timestamps (seconds) to Date objects for JSON serialization
|
||||
// Note: lastSeen from Drizzle is already a Date object (timestamp mode)
|
||||
// lastSync is raw SQL returning seconds, needs conversion
|
||||
return stats.map(stat => ({
|
||||
...stat,
|
||||
lastSync: stat.lastSync ? new Date(stat.lastSync * 1000) : null,
|
||||
// lastSeen is already a Date object from Drizzle, don't convert
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ export async function getAllUsers() {
|
||||
email: users.email,
|
||||
callsign: users.callsign,
|
||||
isAdmin: users.isAdmin,
|
||||
lastSeen: users.lastSeen,
|
||||
createdAt: users.createdAt,
|
||||
updatedAt: users.updatedAt,
|
||||
})
|
||||
@@ -236,3 +237,17 @@ export async function getUserByIdFull(userId) {
|
||||
|
||||
return user || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user's last seen timestamp
|
||||
* @param {number} userId - User ID
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function updateLastSeen(userId) {
|
||||
await db
|
||||
.update(users)
|
||||
.set({
|
||||
lastSeen: new Date(),
|
||||
})
|
||||
.where(eq(users.id, userId));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user