feat(KAN-21): rebuild login verification and two-factor flows
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
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');
|
||||
Reference in New Issue
Block a user