Something went wrong. Try again.
AtAuth
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377/** * Admin Dashboard Routes Tests */import { describe, it, expect, beforeEach, afterEach } from 'vitest';import express from 'express';import request from 'supertest';import crypto from 'crypto';import { createAdminRoutes } from './admin.js';import { DatabaseService } from '../services/database.js';import { createAdminCookie, ADMIN_COOKIE_NAME } from '../utils/proxy-auth.js';
const ADMIN_TOKEN = 'test-admin-token-secret';const SESSION_SECRET = 'test-session-secret-for-admin-32!';
function createTestApp(db: DatabaseService) { const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true }));
const router = createAdminRoutes(db, ADMIN_TOKEN, null, null, null, SESSION_SECRET); app.use('/admin', router); return app;}
function adminCookie(): string { return `${ADMIN_COOKIE_NAME}=${createAdminCookie(SESSION_SECRET, 86400)}`;}
describe('Dashboard Overview', () => { let db: DatabaseService; let app: express.Application;
beforeEach(() => { db = new DatabaseService(':memory:'); app = createTestApp(db); });
afterEach(() => { db.close(); });
it('should render overview page with stats', async () => { db.addProxyAllowedOrigin('https://search.arcnode.xyz', 'SearXNG');
const res = await request(app) .get('/admin/dashboard') .set('Cookie', adminCookie());
expect(res.status).toBe(200); expect(res.text).toContain('Overview'); expect(res.text).toContain('Protected Origins'); expect(res.text).toContain('Access Rules'); expect(res.text).toContain('Active Sessions'); });
it('should redirect to login without cookie', async () => { const res = await request(app) .get('/admin/dashboard') .set('Accept', 'text/html');
expect(res.status).toBe(302); expect(res.headers.location).toBe('/admin/login'); });});
describe('Dashboard Origins', () => { let db: DatabaseService; let app: express.Application;
beforeEach(() => { db = new DatabaseService(':memory:'); app = createTestApp(db); });
afterEach(() => { db.close(); });
it('should render origins page', async () => { const res = await request(app) .get('/admin/dashboard/origins') .set('Cookie', adminCookie());
expect(res.status).toBe(200); expect(res.text).toContain('Protected Origins'); expect(res.text).toContain('Add Origin'); });
it('should list existing origins', async () => { db.addProxyAllowedOrigin('https://search.arcnode.xyz', 'SearXNG');
const res = await request(app) .get('/admin/dashboard/origins') .set('Cookie', adminCookie());
expect(res.status).toBe(200); expect(res.text).toContain('SearXNG'); expect(res.text).toContain('search.arcnode.xyz'); });
it('should add an origin via form POST', async () => { // First get the page to extract CSRF token const page = await request(app) .get('/admin/dashboard/origins') .set('Cookie', adminCookie());
const csrfMatch = page.text.match(/name="_csrf" value="([^"]+)"/); expect(csrfMatch).not.toBeNull(); const csrf = csrfMatch![1];
const res = await request(app) .post('/admin/dashboard/origins') .set('Cookie', adminCookie()) .type('form') .send({ _csrf: csrf, origin: 'https://test.example.com', name: 'Test' });
expect(res.status).toBe(302); expect(res.headers.location).toContain('/admin/dashboard/origins');
// Verify it was added const origins = db.listProxyAllowedOrigins(); expect(origins).toHaveLength(1); expect(origins[0].origin).toBe('https://test.example.com'); });
it('should reject form without CSRF token', async () => { const res = await request(app) .post('/admin/dashboard/origins') .set('Cookie', adminCookie()) .type('form') .send({ origin: 'https://test.example.com', name: 'Test' });
expect(res.status).toBe(403); expect(res.text).toContain('Invalid or expired form submission'); });
it('should delete an origin via form POST', async () => { const origin = db.addProxyAllowedOrigin('https://search.arcnode.xyz', 'SearXNG');
const page = await request(app) .get('/admin/dashboard/origins') .set('Cookie', adminCookie()); const csrfMatch = page.text.match(/name="_csrf" value="([^"]+)"/); const csrf = csrfMatch![1];
const res = await request(app) .post(`/admin/dashboard/origins/${origin.id}/delete`) .set('Cookie', adminCookie()) .type('form') .send({ _csrf: csrf });
expect(res.status).toBe(302); expect(db.listProxyAllowedOrigins()).toHaveLength(0); });});
describe('Dashboard Access Rules', () => { let db: DatabaseService; let app: express.Application;
beforeEach(() => { db = new DatabaseService(':memory:'); app = createTestApp(db); });
afterEach(() => { db.close(); });
it('should render access rules page', async () => { const res = await request(app) .get('/admin/dashboard/access') .set('Cookie', adminCookie());
expect(res.status).toBe(200); expect(res.text).toContain('Access Rules'); expect(res.text).toContain('Add Rule'); });
it('should add a rule via form POST', async () => { const page = await request(app) .get('/admin/dashboard/access') .set('Cookie', adminCookie()); const csrfMatch = page.text.match(/name="_csrf" value="([^"]+)"/); const csrf = csrfMatch![1];
const res = await request(app) .post('/admin/dashboard/access') .set('Cookie', adminCookie()) .type('form') .send({ _csrf: csrf, origin_id: '', rule_type: 'allow', subject_type: 'handle_pattern', subject_value: '*.arcnode.xyz', description: 'PDS users', });
expect(res.status).toBe(302); const rules = db.listProxyAccessRules(); expect(rules).toHaveLength(1); expect(rules[0].subject_value).toBe('*.arcnode.xyz'); });
it('should display existing rules', async () => { db.createProxyAccessRule({ origin_id: null, rule_type: 'allow', subject_type: 'handle_pattern', subject_value: '*.arcnode.xyz', description: 'PDS users', });
const res = await request(app) .get('/admin/dashboard/access') .set('Cookie', adminCookie());
expect(res.text).toContain('*.arcnode.xyz'); expect(res.text).toContain('PDS users'); expect(res.text).toContain('allow'); });});
describe('Dashboard Sessions', () => { let db: DatabaseService; let app: express.Application;
beforeEach(() => { db = new DatabaseService(':memory:'); app = createTestApp(db); });
afterEach(() => { db.close(); });
it('should render sessions page', async () => { const res = await request(app) .get('/admin/dashboard/sessions') .set('Cookie', adminCookie());
expect(res.status).toBe(200); expect(res.text).toContain('Proxy Sessions'); });
it('should list active sessions', async () => { const now = Math.floor(Date.now() / 1000); db.createProxySession({ id: 'sess-1', did: 'did:plc:test123', handle: 'user.bsky.social', created_at: now, expires_at: now + 604800, last_activity: now, });
const res = await request(app) .get('/admin/dashboard/sessions') .set('Cookie', adminCookie());
expect(res.text).toContain('user.bsky.social'); });
it('should revoke a session via form POST', async () => { const now = Math.floor(Date.now() / 1000); db.createProxySession({ id: 'sess-del', did: 'did:plc:test123', handle: 'user.bsky.social', created_at: now, expires_at: now + 604800, last_activity: now, });
const page = await request(app) .get('/admin/dashboard/sessions') .set('Cookie', adminCookie()); const csrfMatch = page.text.match(/name="_csrf" value="([^"]+)"/); const csrf = csrfMatch![1];
const res = await request(app) .post('/admin/dashboard/sessions/sess-del/delete') .set('Cookie', adminCookie()) .type('form') .send({ _csrf: csrf });
expect(res.status).toBe(302); expect(db.getProxySession('sess-del')).toBeNull(); });});
describe('Dashboard Access Check', () => { let db: DatabaseService; let app: express.Application;
beforeEach(() => { db = new DatabaseService(':memory:'); app = createTestApp(db); });
afterEach(() => { db.close(); });
it('should render access check page', async () => { const res = await request(app) .get('/admin/dashboard/check') .set('Cookie', adminCookie());
expect(res.status).toBe(200); expect(res.text).toContain('Access Check Tool'); });
it('should show access check result', async () => { const origin = db.addProxyAllowedOrigin('https://search.arcnode.xyz', 'SearXNG'); db.createProxyAccessRule({ origin_id: null, rule_type: 'allow', subject_type: 'handle_pattern', subject_value: '*.arcnode.xyz', description: null, });
const page = await request(app) .get('/admin/dashboard/check') .set('Cookie', adminCookie()); const csrfMatch = page.text.match(/name="_csrf" value="([^"]+)"/); const csrf = csrfMatch![1];
const res = await request(app) .post('/admin/dashboard/check') .set('Cookie', adminCookie()) .type('form') .send({ _csrf: csrf, did: 'did:plc:test123', handle: 'bkb.arcnode.xyz', origin_id: origin.id.toString(), });
expect(res.status).toBe(200); expect(res.text).toContain('ACCESS ALLOWED'); });
it('should show denied result', async () => { const origin = db.addProxyAllowedOrigin('https://search.arcnode.xyz', 'SearXNG'); db.createProxyAccessRule({ origin_id: null, rule_type: 'allow', subject_type: 'handle_pattern', subject_value: '*.arcnode.xyz', description: null, });
const page = await request(app) .get('/admin/dashboard/check') .set('Cookie', adminCookie()); const csrfMatch = page.text.match(/name="_csrf" value="([^"]+)"/); const csrf = csrfMatch![1];
const res = await request(app) .post('/admin/dashboard/check') .set('Cookie', adminCookie()) .type('form') .send({ _csrf: csrf, did: 'did:plc:outsider', handle: 'user.bsky.social', origin_id: origin.id.toString(), });
expect(res.status).toBe(200); expect(res.text).toContain('ACCESS DENIED'); });});