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:
2026-01-23 09:57:45 +01:00
parent 24e0e3bfdb
commit d1e4c39ad6
6 changed files with 119 additions and 1 deletions

View File

@@ -0,0 +1,86 @@
/**
* Migration: Add last_seen column to users table
*
* This script adds the last_seen column to track when users last accessed the tool.
*/
import Database from 'bun:sqlite';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
// ES module equivalent of __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const dbPath = join(__dirname, '../award.db');
const sqlite = new Database(dbPath);
async function migrate() {
console.log('Starting migration: Add last_seen column...');
try {
// Check if last_seen column already exists
const columnExists = sqlite.query(`
SELECT COUNT(*) as count
FROM pragma_table_info('users')
WHERE name='last_seen'
`).get();
if (columnExists.count > 0) {
console.log('Column last_seen already exists. Skipping...');
} else {
// Add last_seen column
sqlite.exec(`
ALTER TABLE users
ADD COLUMN last_seen INTEGER
`);
console.log('Added last_seen column to users table');
}
console.log('Migration complete! last_seen column added to database.');
} catch (error) {
console.error('Migration failed:', error);
sqlite.close();
process.exit(1);
}
sqlite.close();
}
async function rollback() {
console.log('Starting rollback: Remove last_seen column...');
try {
// SQLite doesn't support DROP COLUMN directly before version 3.35.5
// For older versions, we need to recreate the table
console.log('Note: SQLite does not support DROP COLUMN. Manual cleanup required.');
console.log('To rollback: Recreate users table without last_seen column');
// For SQLite 3.35.5+, you can use:
// sqlite.exec(`ALTER TABLE users DROP COLUMN last_seen`);
console.log('Rollback note issued.');
} catch (error) {
console.error('Rollback failed:', error);
sqlite.close();
process.exit(1);
}
sqlite.close();
}
// Check if this is a rollback
const args = process.argv.slice(2);
if (args.includes('--rollback') || args.includes('-r')) {
rollback().then(() => {
console.log('Rollback script completed');
process.exit(0);
});
} else {
// Run migration
migrate().then(() => {
console.log('Migration script completed successfully');
process.exit(0);
});
}