- Move service account credentials to .env (loaded server-side only) - server.js: inject credentials in proxy, strip any client-provided creds, replace deprecated url.parse with new URL - auth.js / dashboard.js: remove all hardcoded passwords from client code - dashboard.js: remove broken category filter, fix redundant user.info call (use stored userId), add HTML escaping against XSS - login.html: remove unused password field - dashboard.html: remove broken category filter UI - Add .gitignore to exclude .env and node_modules - Add .env.example as configuration template Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
3.7 KiB
JavaScript
95 lines
3.7 KiB
JavaScript
const OLIVER_AUTH_CONFIG = {
|
|
apiBaseUrl: '/api',
|
|
clientId: '7',
|
|
};
|
|
|
|
const TMM_AUTH_CONFIG = {
|
|
apiBaseUrl: '/api',
|
|
clientId: '7',
|
|
};
|
|
|
|
async function handleLogin(authConfig, loginType) {
|
|
const username = document.getElementById('username').value.trim();
|
|
const errorMessage = document.getElementById('errorMessage');
|
|
const isOliver = loginType === 'oliver';
|
|
const loginButton = document.getElementById(isOliver ? 'oliverLoginButton' : 'tmmLoginButton');
|
|
const buttonText = document.getElementById(isOliver ? 'oliverButtonText' : 'tmmButtonText');
|
|
const spinner = document.getElementById(isOliver ? 'oliverSpinner' : 'tmmSpinner');
|
|
|
|
errorMessage.style.display = 'none';
|
|
|
|
if (!username) {
|
|
errorMessage.textContent = 'Please enter your username.';
|
|
errorMessage.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
loginButton.disabled = true;
|
|
buttonText.textContent = 'Signing in...';
|
|
spinner.style.display = 'inline-block';
|
|
|
|
try {
|
|
// Step 1: Resolve username → userId
|
|
const userInfoParams = new URLSearchParams({
|
|
command: 'user.info',
|
|
authDomain: 'local',
|
|
clientId: '6',
|
|
username,
|
|
domain: 'local',
|
|
});
|
|
|
|
const userInfoRes = await fetch(`${authConfig.apiBaseUrl}?${userInfoParams}`, {
|
|
headers: { Accept: 'text/xml' },
|
|
});
|
|
const userInfoDoc = new DOMParser().parseFromString(await userInfoRes.text(), 'text/xml');
|
|
|
|
const userInfoError = userInfoDoc.querySelector('error');
|
|
if (userInfoError) {
|
|
throw new Error(userInfoError.querySelector('message')?.textContent || 'User not found');
|
|
}
|
|
|
|
const userIdNode = userInfoDoc.querySelector('user > id') || userInfoDoc.querySelector('id');
|
|
if (!userIdNode) throw new Error('User not found. Please check your username.');
|
|
const userId = userIdNode.textContent;
|
|
|
|
// Step 2: Create external session for the user
|
|
const sessionParams = new URLSearchParams({
|
|
command: 'user.session.extern.add',
|
|
authDomain: 'local',
|
|
clientId: authConfig.clientId,
|
|
username,
|
|
userId,
|
|
});
|
|
|
|
const sessionRes = await fetch(`${authConfig.apiBaseUrl}?${sessionParams}`, {
|
|
headers: { Accept: 'text/xml' },
|
|
});
|
|
const sessionDoc = new DOMParser().parseFromString(await sessionRes.text(), 'text/xml');
|
|
|
|
const sessionError = sessionDoc.querySelector('error');
|
|
if (sessionError) {
|
|
throw new Error(sessionError.querySelector('message')?.textContent || 'Login failed');
|
|
}
|
|
|
|
const externSessionId = sessionDoc.querySelector('externSessionId')?.textContent;
|
|
if (!externSessionId) throw new Error('No session received from server');
|
|
|
|
sessionStorage.setItem('isAuthenticated', 'true');
|
|
sessionStorage.setItem('username', username);
|
|
sessionStorage.setItem('userId', userId);
|
|
sessionStorage.setItem('externSessionId', externSessionId);
|
|
sessionStorage.setItem('authConfig', JSON.stringify(authConfig));
|
|
|
|
window.location.href = 'dashboard.html';
|
|
} catch (error) {
|
|
console.error('Login error:', error);
|
|
errorMessage.textContent = error.message || 'An error occurred. Please try again.';
|
|
errorMessage.style.display = 'block';
|
|
loginButton.disabled = false;
|
|
buttonText.textContent = isOliver ? 'Oliver Login' : '3M Login';
|
|
spinner.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
document.getElementById('oliverLoginButton').addEventListener('click', () => handleLogin(OLIVER_AUTH_CONFIG, 'oliver'));
|
|
document.getElementById('tmmLoginButton').addEventListener('click', () => handleLogin(TMM_AUTH_CONFIG, '3m'));
|