updated authentication of instances
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
<th>Payment Plan</th>
|
||||
<th>Main URL</th>
|
||||
<th>Status</th>
|
||||
<th>Connection Token</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -64,6 +65,19 @@
|
||||
{{ instance.status|title }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if instance.connection_token %}
|
||||
<span class="badge bg-success" data-bs-toggle="tooltip" title="Instance is authenticated">
|
||||
Authenticated
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-warning" data-bs-toggle="tooltip" title="Click to authenticate instance">
|
||||
<a href="#" class="text-dark text-decoration-none" onclick="showAuthModal('{{ instance.main_url }}', {{ instance.id }})">
|
||||
Generate Token
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="editInstance({{ instance.id }})">
|
||||
@@ -173,6 +187,37 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auth Modal -->
|
||||
<div class="modal fade" id="authModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Authenticate Instance</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="authForm">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<input type="hidden" id="instance_url" name="instance_url">
|
||||
<input type="hidden" id="instance_id" name="instance_id">
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" onclick="authenticateInstance()">Authenticate</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
@@ -181,11 +226,13 @@
|
||||
let addInstanceModal;
|
||||
let editInstanceModal;
|
||||
let addExistingInstanceModal;
|
||||
let authModal;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
addInstanceModal = new bootstrap.Modal(document.getElementById('addInstanceModal'));
|
||||
editInstanceModal = new bootstrap.Modal(document.getElementById('editInstanceModal'));
|
||||
addExistingInstanceModal = new bootstrap.Modal(document.getElementById('addExistingInstanceModal'));
|
||||
authModal = new bootstrap.Modal(document.getElementById('authModal'));
|
||||
|
||||
// Initialize tooltips
|
||||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
@@ -409,5 +456,95 @@ async function submitAddExistingInstance() {
|
||||
alert('Error adding instance: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function showAuthModal(instanceUrl, instanceId) {
|
||||
document.getElementById('instance_url').value = instanceUrl;
|
||||
document.getElementById('instance_id').value = instanceId;
|
||||
document.getElementById('authForm').reset();
|
||||
authModal.show();
|
||||
}
|
||||
|
||||
async function authenticateInstance() {
|
||||
const form = document.getElementById('authForm');
|
||||
const formData = new FormData(form);
|
||||
const instanceUrl = formData.get('instance_url').replace(/\/+$/, ''); // Remove trailing slashes
|
||||
const instanceId = formData.get('instance_id');
|
||||
const email = formData.get('email');
|
||||
const password = formData.get('password');
|
||||
|
||||
try {
|
||||
// First login to get token
|
||||
const loginResponse = await fetch(`${instanceUrl}/admin/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ email, password })
|
||||
});
|
||||
|
||||
if (!loginResponse.ok) {
|
||||
const errorData = await loginResponse.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Login failed');
|
||||
}
|
||||
|
||||
const { token } = await loginResponse.json();
|
||||
|
||||
// Then create management API key
|
||||
const keyResponse = await fetch(`${instanceUrl}/admin/management-api-key`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: `Connection from ${window.location.hostname}`
|
||||
})
|
||||
});
|
||||
|
||||
if (!keyResponse.ok) {
|
||||
const errorData = await keyResponse.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Failed to create API key');
|
||||
}
|
||||
|
||||
const { api_key } = await keyResponse.json();
|
||||
|
||||
// Save the token to our database
|
||||
const saveResponse = await fetch(`/instances/${instanceId}/save-token`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': formData.get('csrf_token')
|
||||
},
|
||||
body: JSON.stringify({ token: api_key })
|
||||
});
|
||||
|
||||
if (!saveResponse.ok) {
|
||||
const errorData = await saveResponse.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || 'Failed to save token');
|
||||
}
|
||||
|
||||
// Show success and refresh
|
||||
authModal.hide();
|
||||
location.reload();
|
||||
} catch (error) {
|
||||
console.error('Authentication error:', error);
|
||||
alert('Error: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function copyConnectionToken(button) {
|
||||
const input = button.previousElementSibling;
|
||||
input.select();
|
||||
document.execCommand('copy');
|
||||
|
||||
// Show feedback
|
||||
const originalText = button.innerHTML;
|
||||
button.innerHTML = '<i class="fas fa-check"></i>';
|
||||
setTimeout(() => {
|
||||
button.innerHTML = originalText;
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user