// Active Devices (mobile session view/revoke) — controller tests. The // mobileSessions model is stubbed, so these are DB-free. process.env.JWT_SECRET = process.env.JWT_SECRET || 'test-secret' process.env.SECRET_ENC_KEY = process.env.SECRET_ENC_KEY || 'unit-test-enc-key' process.env.DB_HOST = '127.0.0.1' process.env.DB_PORT = '59999' const { test, beforeEach, after } = require('node:test') const assert = require('node:assert/strict') const account = require('../src/router/v1/admin/account.controller') const mobileSessions = require('../src/model/mobileSessions/mobileSessions.model') const activity = require('../src/model/activity/activity.model') const db = require('../src/utils/db') after(() => db.close()) let logged beforeEach(() => { logged = [] activity.log = async (e) => { logged.push(e) } }) function res() { return { statusCode: 200, body: null, status(c) { this.statusCode = c; return this }, json(b) { this.body = b; return this }, } } test('listSessions returns active devices without any token material', async () => { mobileSessions.listActiveForUser = async (uid) => { assert.equal(uid, 7) return [ { id: 3, device_name: 'Pixel 8', user_agent: 'okhttp', created_at: 'c3', last_used_at: 'u3', expires_at: 'e3', token_hash: 'SECRET' }, { id: 1, device_name: null, user_agent: null, created_at: 'c1', last_used_at: null, expires_at: 'e1' }, ] } const r = res() await account.listSessions({ user: { id: 7 } }, r) assert.equal(r.body.length, 2) assert.deepEqual(r.body[0], { id: 3, deviceName: 'Pixel 8', userAgent: 'okhttp', createdAt: 'c3', lastUsedAt: 'u3', expiresAt: 'e3' }) // last_used_at falls back to created_at when null; no token/hash leaks. assert.equal(r.body[1].lastUsedAt, 'c1') assert.equal(JSON.stringify(r.body).includes('SECRET'), false) }) test('revokeSession is ownership-scoped and audits a real revoke', async () => { let args = null mobileSessions.revokeByIdForUser = async (id, uid) => { args = [id, uid]; return 1 } const r = res() await account.revokeSession({ user: { id: 7 }, params: { id: '3' } }, r) assert.deepEqual(args, [3, 7], 'revokes by id scoped to the caller') assert.deepEqual(r.body, { revoked: true }) assert.equal(logged.at(-1).action, 'auth.mobile.session.revoke') }) test('revokeSession on a non-owned/absent id is idempotent and not audited', async () => { mobileSessions.revokeByIdForUser = async () => 0 const r = res() await account.revokeSession({ user: { id: 7 }, params: { id: '999' } }, r) assert.deepEqual(r.body, { revoked: false }) assert.equal(logged.length, 0, 'nothing revoked → nothing logged') })