2026-05-27 14:21:32 -04:00
import { test } from 'node:test' ;
import assert from 'node:assert/strict' ;
import { isTestDbConfigured , setupTestDb } from '../helpers/setup-db.js' ;
import express from 'express' ;
2026-05-27 14:24:56 -04:00
import session from 'express-session' ;
2026-05-27 14:21:32 -04:00
import authRouter from '../../src/routes/auth.js' ;
async function appWithAuth ( pool ) {
process . env . DATABASE _URL = process . env . TEST _DATABASE _URL ;
const app = express ( ) ;
app . use ( express . json ( ) ) ;
app . use ( '/api/v1/auth' , authRouter ) ;
return new Promise ( r => {
const srv = app . listen ( 0 , '127.0.0.1' , ( ) => {
r ( { baseUrl : 'http://127.0.0.1:' + srv . address ( ) . port , close : ( ) => new Promise ( rs => srv . close ( rs ) ) } ) ;
} ) ;
} ) ;
}
test ( 'GET /auth/setup-required returns { required: true } on empty users (modulo dev seed)' , { skip : ! isTestDbConfigured ( ) && 'TEST_DATABASE_URL not set' } , async ( ) => {
const pool = await setupTestDb ( ) ;
const { baseUrl , close } = await appWithAuth ( pool ) ;
try {
const res = await fetch ( baseUrl + '/api/v1/auth/setup-required' ) ;
assert . equal ( res . status , 200 ) ;
assert . deepEqual ( await res . json ( ) , { required : true } ) ;
} finally { await close ( ) ; await pool . end ( ) ; }
} ) ;
test ( 'GET /auth/setup-required returns { required: false } once a real user exists' , { skip : ! isTestDbConfigured ( ) && 'TEST_DATABASE_URL not set' } , async ( ) => {
const pool = await setupTestDb ( ) ;
await pool . query ( ` INSERT INTO users (username, password_hash) VALUES ('admin', 'x') ` ) ;
const { baseUrl , close } = await appWithAuth ( pool ) ;
try {
const res = await fetch ( baseUrl + '/api/v1/auth/setup-required' ) ;
assert . deepEqual ( await res . json ( ) , { required : false } ) ;
} finally { await close ( ) ; await pool . end ( ) ; }
} ) ;
2026-05-27 14:24:56 -04:00
async function appWithSession ( pool ) {
process . env . DATABASE _URL = process . env . TEST _DATABASE _URL ;
process . env . SESSION _SECRET = 'test' ;
process . env . AUTH _ENABLED = 'true' ;
const ConnectPg = ( await import ( 'connect-pg-simple' ) ) . default ( session ) ;
const app = express ( ) ;
app . use ( express . json ( ) ) ;
app . use ( session ( {
store : new ConnectPg ( { pool , tableName : 'sessions' } ) ,
secret : 'test' , name : 'dragonflight.sid' ,
cookie : { httpOnly : true , sameSite : 'lax' , secure : false , maxAge : 8 * 3600 * 1000 } ,
rolling : false , resave : false , saveUninitialized : false ,
} ) ) ;
app . use ( '/api/v1/auth' , authRouter ) ;
return new Promise ( r => {
const srv = app . listen ( 0 , '127.0.0.1' , ( ) => {
r ( { baseUrl : 'http://127.0.0.1:' + srv . address ( ) . port , close : ( ) => new Promise ( rs => srv . close ( rs ) ) } ) ;
} ) ;
} ) ;
}
test ( 'POST /auth/setup creates the first admin and returns a session cookie' , { skip : ! isTestDbConfigured ( ) && 'TEST_DATABASE_URL not set' } , async ( ) => {
const pool = await setupTestDb ( ) ;
const { baseUrl , close } = await appWithSession ( pool ) ;
try {
const res = await fetch ( baseUrl + '/api/v1/auth/setup' , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON . stringify ( { username : 'admin' , password : 'correct-horse-battery' } ) ,
} ) ;
assert . equal ( res . status , 200 ) ;
const body = await res . json ( ) ;
assert . equal ( body . user . username , 'admin' ) ;
assert . match ( res . headers . get ( 'set-cookie' ) || '' , /dragonflight\.sid=/ ) ;
const { rows } = await pool . query ( ` SELECT COUNT(*)::int AS n FROM users WHERE username='admin' ` ) ;
assert . equal ( rows [ 0 ] . n , 1 ) ;
} finally { await close ( ) ; await pool . end ( ) ; }
} ) ;
test ( 'POST /auth/setup is 409 once a real user exists' , { skip : ! isTestDbConfigured ( ) && 'TEST_DATABASE_URL not set' } , async ( ) => {
const pool = await setupTestDb ( ) ;
await pool . query ( ` INSERT INTO users (username, password_hash) VALUES ('existing', 'x') ` ) ;
const { baseUrl , close } = await appWithSession ( pool ) ;
try {
const res = await fetch ( baseUrl + '/api/v1/auth/setup' , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON . stringify ( { username : 'admin' , password : 'correct-horse-battery' } ) ,
} ) ;
assert . equal ( res . status , 409 ) ;
assert . equal ( ( await res . json ( ) ) . error , 'setup already complete' ) ;
} finally { await close ( ) ; await pool . end ( ) ; }
} ) ;
test ( 'POST /auth/setup rejects passwords shorter than 12 chars' , { skip : ! isTestDbConfigured ( ) && 'TEST_DATABASE_URL not set' } , async ( ) => {
const pool = await setupTestDb ( ) ;
const { baseUrl , close } = await appWithSession ( pool ) ;
try {
const res = await fetch ( baseUrl + '/api/v1/auth/setup' , {
method : 'POST' , headers : { 'Content-Type' : 'application/json' } ,
body : JSON . stringify ( { username : 'admin' , password : 'short' } ) ,
} ) ;
assert . equal ( res . status , 400 ) ;
} finally { await close ( ) ; await pool . end ( ) ; }
} ) ;