120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
import { fileURLToPath } from 'node:url';
|
|
import vue from '@vitejs/plugin-vue';
|
|
import tailwind from '@tailwindcss/vite';
|
|
import { createServer } from 'vite';
|
|
|
|
// Isolated Inertia transport fixture; real Fortify sessions are covered by PHPUnit.
|
|
const server = await createServer({
|
|
configFile: false,
|
|
cacheDir: 'node_modules/.vite/auth-fixture',
|
|
plugins: [vue(), tailwind()],
|
|
resolve: {
|
|
alias: {
|
|
'@': fileURLToPath(new URL('../../resources/js', import.meta.url)),
|
|
},
|
|
},
|
|
server: { host: '127.0.0.1', port: 4177, strictPort: true, hmr: false },
|
|
appType: 'custom',
|
|
});
|
|
|
|
server.middlewares.use(async (request, response, next) => {
|
|
const url = new URL(request.url, 'http://localhost');
|
|
const pages = {
|
|
'/login': 'Login',
|
|
'/two-factor-challenge': 'TwoFactorChallenge',
|
|
'/email/verify': 'VerifyEmail',
|
|
'/email/verification-notification': 'VerifyEmail',
|
|
'/dashboard': 'Destination',
|
|
'/logout': 'Login',
|
|
'/forgot-password': 'Destination',
|
|
'/': 'Destination',
|
|
};
|
|
if (!(url.pathname in pages)) {
|
|
return next();
|
|
}
|
|
const mutation = request.method === 'POST';
|
|
const result =
|
|
request.headers.cookie?.match(/auth_test_result=(\w+)/)?.[1] ??
|
|
'success';
|
|
if (mutation && ['server', 'expired', 'limited'].includes(result)) {
|
|
response.statusCode = { server: 503, expired: 419, limited: 429 }[
|
|
result
|
|
];
|
|
response.setHeader('Content-Type', 'text/html');
|
|
response.end('<h1>Simulated failed response</h1>');
|
|
return;
|
|
}
|
|
let body = '';
|
|
if (mutation) {
|
|
for await (const chunk of request) {
|
|
body += chunk;
|
|
}
|
|
}
|
|
const submitted = body ? JSON.parse(body) : {};
|
|
let path = url.pathname;
|
|
let errors = {};
|
|
let status;
|
|
if (mutation && result === 'validation') {
|
|
path = new URL(request.headers.referer).pathname;
|
|
const field =
|
|
path === '/login'
|
|
? 'email'
|
|
: 'recovery_code' in submitted
|
|
? 'recovery_code'
|
|
: 'code';
|
|
errors = { [field]: 'These details could not be verified.' };
|
|
} else if (mutation) {
|
|
if (path === '/email/verification-notification') {
|
|
path = '/email/verify';
|
|
status = 'verification-link-sent';
|
|
} else if (path === '/logout') {
|
|
path = '/login';
|
|
} else {
|
|
path =
|
|
result === 'challenge' ? '/two-factor-challenge' : '/dashboard';
|
|
}
|
|
}
|
|
const page = {
|
|
component: pages[path],
|
|
url: path,
|
|
version: null,
|
|
clearHistory: false,
|
|
encryptHistory: false,
|
|
props: {
|
|
name: 'KanbanGit',
|
|
errors,
|
|
status,
|
|
canResetPassword: !url.searchParams.has('no-reset'),
|
|
auth: {
|
|
user:
|
|
path === '/email/verify'
|
|
? {
|
|
id: 1,
|
|
name: 'Alex Morgan',
|
|
email: 'alex.morgan@example.test',
|
|
}
|
|
: null,
|
|
},
|
|
},
|
|
};
|
|
response.setHeader('Vary', 'X-Inertia');
|
|
if (request.headers['x-inertia']) {
|
|
response.setHeader('X-Inertia', 'true');
|
|
response.setHeader('Content-Type', 'application/json');
|
|
response.end(JSON.stringify(page));
|
|
return;
|
|
}
|
|
const escaped = JSON.stringify(page)
|
|
.replaceAll('&', '&')
|
|
.replaceAll('"', '"')
|
|
.replaceAll('<', '<');
|
|
const html =
|
|
'<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head><body><div id="app" data-page="' +
|
|
escaped +
|
|
'"></div><script type="module" src="/tests/Fixtures/auth-preview.mjs"></script></body></html>';
|
|
response.setHeader('Content-Type', 'text/html');
|
|
response.end(await server.transformIndexHtml(request.url, html));
|
|
});
|
|
await server.listen();
|
|
console.log('Auth fixture ready at http://127.0.0.1:4177/login');
|