Files
panel/includes/auth.js
MCHost d38e2ad1f1 Refactor: Initial code split into includes directory for modularity
- Reorganized backend logic by moving API, authentication, Docker, status, and WebSocket handling into separate modules (api.js, auth.js, docker.js, status.js, websocket.js) within ./includes/
- Converted codebase to ES modules with import/export syntax for modern JavaScript
- Updated index.js to serve as main entry point, importing from ./includes/
- Reduced code duplication and improved readability with modularized functions
- Ensured full functionality preservation, including Docker stats and WebSocket communication
- Updated README to reflect new folder structure and ES module setup
2025-06-16 12:30:18 -04:00

88 lines
3.2 KiB
JavaScript

import unirest from 'unirest';
import { randomBytes } from 'crypto';
const temporaryLinks = new Map();
setInterval(() => {
const now = Date.now();
for (const [linkId, linkData] of temporaryLinks.entries()) {
if (linkData.expiresAt < now) temporaryLinks.delete(linkId);
}
}, parseInt(process.env.TEMP_LINKS_CLEANUP_INTERVAL_MS, 10));
export async function generateLoginLink(req, res) {
try {
const { secretKey, username } = req.body;
if (secretKey !== process.env.ADMIN_SECRET_KEY) return res.status(401).json({ error: 'Invalid secret key' });
if (!username) return res.status(400).json({ error: 'Username is required' });
const tokenResponse = await unirest
.post(process.env.AUTH_ENDPOINT)
.headers({ 'Accept': 'application/json', 'Content-Type': 'application/json' })
.send({ username, password: process.env.AUTH_PASSWORD });
if (!tokenResponse.body.token) return res.status(500).json({ error: 'Failed to generate API key' });
const apiKey = tokenResponse.body.token;
const linkId = randomBytes(parseInt(process.env.LINK_ID_BYTES, 10)).toString('hex');
const loginLink = `${process.env.AUTO_LOGIN_LINK_PREFIX}${linkId}`;
temporaryLinks.set(linkId, {
apiKey,
username,
expiresAt: Date.now() + parseInt(process.env.LINK_EXPIRY_SECONDS, 10) * 1000
});
setTimeout(() => temporaryLinks.delete(linkId), parseInt(process.env.LINK_EXPIRY_SECONDS, 10) * 1000);
res.json({ loginLink });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
}
export function handleAutoLogin(req, res) {
const { linkId } = req.params;
const linkData = temporaryLinks.get(linkId);
if (!linkData || linkData.expiresAt < Date.now()) {
temporaryLinks.delete(linkId);
return res.send(`
<html>
<head>
<meta http-equiv="refresh" content="3;url=${process.env.AUTO_LOGIN_REDIRECT_URL}">
<style>
body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #111827; font-family: 'Arial', sans-serif; }
.notification { background-color: #1f2937; color: white; padding: 16px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; gap: 12px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); max-width: 400px; width: 100%; }
h1 { font-size: 2.25em; color: white; text-align: center; margin: 0; }
.spinner { border: 4px solid rgba(255, 255, 255, 0.3); border-top: 4px solid #ffffff; border-radius: 50%; width: 24px; height: 24px; animation: spin 1s linear infinite; }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
</style>
</head>
<body>
<div class="notification">
<span class="spinner"></span>
<h1>Login Expired.</h1>
<h1>Redirecting...</h1>
</div>
</body>
</html>
`);
}
temporaryLinks.delete(linkId);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Auto Login</title>
<script>
localStorage.setItem('apiKey', '${linkData.apiKey}');
window.location.href = '/';
</script>
</head>
<body>
<p>Logging in...</p>
</body>
</html>
`);
}