| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import { mkdtempSync } from 'node:fs'
- import { tmpdir } from 'node:os'
- import { join } from 'node:path'
- import request from 'supertest'
- import { afterEach, describe, expect, it } from 'vitest'
- import { createApplication, type ApplicationRuntime } from '../../src/server/app.js'
- import type { ServerConfig } from '../../src/server/config.js'
- const runtimes: ApplicationRuntime[] = []
- afterEach(() => { for (const runtime of runtimes.splice(0)) runtime.close() })
- describe('authenticated read cache routes', () => {
- it('hits cached reads, honors fresh reads and never bypasses logout authentication', async () => {
- const home = mkdtempSync(join(tmpdir(), 'yaoyao-read-cache-routes-'))
- const config: ServerConfig = { host: '127.0.0.1', port: 8800, upstream: new URL('http://127.0.0.1:19119'),
- allowedHosts: new Set(), home, mediaRoot: home, attachmentsRoot: home, imagesRoot: home, mediaOwner: 'test',
- allowInsecureLan: false, insecureLan: false, production: false }
- let sessionReads = 0, statusReads = 0, currentTitle = 'original'
- const runtime = createApplication({ config, fetchImpl: (async (input, init) => {
- const path = new URL(String(input)).pathname
- if (path === '/api/status') { statusReads++; return Response.json({ auth_required: false }) }
- if (path === '/api/profiles' || path === '/api/plugins/yaoyao/profiles') return Response.json({ profiles: [{ name: 'default', is_default: true }] })
- if (path === '/api/sessions' && (init?.method ?? 'GET') === 'GET') { sessionReads++; return Response.json({ sessions: [{ id: 'one', title: currentTitle }] }) }
- if (path === '/api/sessions/one' && init?.method === 'PATCH') { currentTitle = 'renamed'; return Response.json({ ok: true }) }
- return Response.json({ ok: true })
- }) as typeof fetch })
- runtimes.push(runtime)
- const agent = request.agent(runtime.app.callback()), origin = 'http://127.0.0.1:8800'
- const start = await agent.get('/api/app/bootstrap').set('Host', '127.0.0.1:8800').expect(200)
- const login = await agent.post('/api/app/login').set('Host', '127.0.0.1:8800').set('Origin', origin)
- .set('X-CSRF-Token', start.body.csrfToken).send({ username: 'admin', password: 'admin' }).expect(200)
- await agent.put('/api/app/account/credentials').set('Host', '127.0.0.1:8800').set('Origin', origin)
- .set('X-CSRF-Token', login.body.csrfToken).send({ currentPassword: 'admin', newPassword: 'fixture-password', username: 'owner' }).expect(200)
- const statusBefore = statusReads
- const first = await agent.get('/api/sessions').set('Host', '127.0.0.1:8800').expect(200)
- const statusAfterColdRead = statusReads
- const second = await agent.get('/api/sessions').set('Host', '127.0.0.1:8800').expect(200)
- expect(second.body).toEqual(first.body)
- expect(sessionReads).toBe(1)
- expect(statusAfterColdRead - statusBefore).toBeLessThanOrEqual(1)
- expect(statusReads).toBe(statusAfterColdRead)
- currentTitle = 'external-change'
- const fresh = await agent.get('/api/sessions').set('Host', '127.0.0.1:8800').set('X-Yaoyao-Cache', 'bypass').expect(200)
- expect(fresh.body.sessions[0].title).toBe('external-change')
- const after = await agent.get('/api/sessions').set('Host', '127.0.0.1:8800').expect(200)
- expect(after.body.sessions[0].title).toBe('external-change')
- expect(sessionReads).toBe(3)
- await agent.patch('/api/sessions/one').set('Host', '127.0.0.1:8800').send({ title: 'renamed' }).expect(200)
- const renamed = await agent.get('/api/sessions').set('Host', '127.0.0.1:8800').expect(200)
- expect(renamed.body.sessions[0].title).toBe('renamed')
- expect(sessionReads).toBe(4)
- await agent.post('/auth/logout').set('Host', '127.0.0.1:8800').send({}).expect(200)
- await agent.get('/api/sessions').set('Host', '127.0.0.1:8800').expect(401)
- expect(sessionReads).toBe(4)
- })
- })
|