A modern web interface for Luanti (Minetest) server management with ContentDB integration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
116 lines
4.6 KiB
Plaintext
116 lines
4.6 KiB
Plaintext
<%
|
|
const body = `
|
|
<div style="max-width: 500px; margin: 2rem auto;">
|
|
<div class="card">
|
|
<div class="card-header" style="text-align: center;">
|
|
<h2>${isFirstUser ? 'Setup Administrator Account' : 'Create Account'}</h2>
|
|
<p style="color: var(--text-secondary); margin: 0;">
|
|
${isFirstUser ?
|
|
'Create the first administrator account for this Luanti server' :
|
|
'Join this Luanti server management team'
|
|
}
|
|
</p>
|
|
</div>
|
|
|
|
${typeof error !== 'undefined' ? `
|
|
<div class="alert alert-danger">
|
|
<strong>Error:</strong> ${error}
|
|
</div>
|
|
` : ''}
|
|
|
|
${isFirstUser ? `
|
|
<div class="alert alert-info">
|
|
<strong>First User Setup:</strong> You are creating the first administrator account for this server. All users have full admin privileges.
|
|
</div>
|
|
` : ''}
|
|
|
|
<form method="POST" action="/register">
|
|
${typeof csrfToken !== 'undefined' && csrfToken ? `<input type="hidden" name="_csrf" value="${csrfToken}">` : ''}
|
|
<div class="form-group">
|
|
<label for="username">Username*</label>
|
|
<input type="text"
|
|
id="username"
|
|
name="username"
|
|
class="form-control"
|
|
value="${typeof formData !== 'undefined' ? formData.username || '' : ''}"
|
|
required
|
|
pattern="[a-zA-Z0-9_-]{3,20}"
|
|
title="3-20 characters, letters, numbers, underscore, or hyphen only"
|
|
data-validate-name
|
|
autofocus
|
|
autocomplete="username">
|
|
<small style="color: var(--text-secondary);">3-20 characters, letters, numbers, underscore, or hyphen only</small>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="password">Password*</label>
|
|
<input type="password"
|
|
id="password"
|
|
name="password"
|
|
class="form-control"
|
|
required
|
|
minlength="8"
|
|
autocomplete="new-password">
|
|
<small style="color: var(--text-secondary);">At least 8 characters long</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="confirmPassword">Confirm Password*</label>
|
|
<input type="password"
|
|
id="confirmPassword"
|
|
name="confirmPassword"
|
|
class="form-control"
|
|
required
|
|
minlength="8"
|
|
autocomplete="new-password">
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 2rem;">
|
|
<a href="/login" class="btn btn-outline">
|
|
Already have an account?
|
|
</a>
|
|
<button type="submit" class="btn btn-success">
|
|
${isFirstUser ? 'Setup Account' : 'Create Account'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div style="text-align: center; margin-top: 1rem; color: var(--text-secondary); font-size: 0.875rem;">
|
|
<p>
|
|
${isFirstUser ?
|
|
'This will be the primary administrator account.' :
|
|
'All accounts have full server administration privileges.'
|
|
}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Client-side password confirmation validation
|
|
document.getElementById('confirmPassword').addEventListener('input', function() {
|
|
const password = document.getElementById('password').value;
|
|
const confirmPassword = this.value;
|
|
|
|
if (password && confirmPassword) {
|
|
if (password !== confirmPassword) {
|
|
this.setCustomValidity('Passwords do not match');
|
|
} else {
|
|
this.setCustomValidity('');
|
|
}
|
|
}
|
|
});
|
|
|
|
document.getElementById('password').addEventListener('input', function() {
|
|
const confirmPassword = document.getElementById('confirmPassword');
|
|
if (confirmPassword.value) {
|
|
confirmPassword.dispatchEvent(new Event('input'));
|
|
}
|
|
});
|
|
</script>
|
|
`;
|
|
%>
|
|
|
|
<%- include('../layout', { body: body, currentPage: 'register', title: title }) %> |