mirror of
https://github.com/netbirdio/dex.git
synced 2026-05-22 18:43:53 -07:00
6f2e233c7a
Signed-off-by: maksim.nabokikh <max.nabokih@gmail.com>
155 lines
5.1 KiB
JavaScript
155 lines
5.1 KiB
JavaScript
(function() {
|
||
const crossClientInput = document.getElementById("cross_client_input");
|
||
const crossClientList = document.getElementById("cross-client-list");
|
||
const addClientBtn = document.getElementById("add-cross-client");
|
||
const scopesList = document.getElementById("scopes-list");
|
||
const customScopeInput = document.getElementById("custom_scope_input");
|
||
const addCustomScopeBtn = document.getElementById("add-custom-scope");
|
||
|
||
// Default scopes that should be checked by default
|
||
const defaultScopes = ["openid", "profile", "email", "offline_access"];
|
||
|
||
// Check default scopes on page load
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
const checkboxes = scopesList.querySelectorAll('input[type="checkbox"]');
|
||
checkboxes.forEach(cb => {
|
||
if (defaultScopes.includes(cb.value)) {
|
||
cb.checked = true;
|
||
}
|
||
});
|
||
});
|
||
|
||
function addCrossClient(value) {
|
||
const trimmed = value.trim();
|
||
if (!trimmed) return;
|
||
|
||
const chip = document.createElement("div");
|
||
chip.className = "chip";
|
||
|
||
const text = document.createElement("span");
|
||
text.textContent = trimmed;
|
||
|
||
const hidden = document.createElement("input");
|
||
hidden.type = "hidden";
|
||
hidden.name = "cross_client";
|
||
hidden.value = trimmed;
|
||
|
||
const remove = document.createElement("button");
|
||
remove.type = "button";
|
||
remove.textContent = "×";
|
||
remove.onclick = () => crossClientList.removeChild(chip);
|
||
|
||
chip.append(text, hidden, remove);
|
||
crossClientList.appendChild(chip);
|
||
}
|
||
|
||
function addCustomScope(scope) {
|
||
const trimmed = scope.trim();
|
||
if (!trimmed || !scopesList) return;
|
||
|
||
// Check if scope already exists
|
||
const existingCheckboxes = scopesList.querySelectorAll('input[type="checkbox"]');
|
||
for (const cb of existingCheckboxes) {
|
||
if (cb.value === trimmed) {
|
||
cb.checked = true;
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Add new scope checkbox
|
||
const scopeItem = document.createElement("div");
|
||
scopeItem.className = "scope-item";
|
||
|
||
const checkbox = document.createElement("input");
|
||
checkbox.type = "checkbox";
|
||
checkbox.name = "extra_scopes";
|
||
checkbox.value = trimmed;
|
||
checkbox.id = "scope_custom_" + trimmed;
|
||
checkbox.checked = true;
|
||
|
||
const label = document.createElement("label");
|
||
label.htmlFor = checkbox.id;
|
||
label.textContent = trimmed;
|
||
|
||
scopeItem.append(checkbox, label);
|
||
scopesList.appendChild(scopeItem);
|
||
}
|
||
|
||
addClientBtn?.addEventListener("click", () => {
|
||
addCrossClient(crossClientInput.value);
|
||
crossClientInput.value = "";
|
||
crossClientInput.focus();
|
||
});
|
||
|
||
crossClientInput?.addEventListener("keydown", (e) => {
|
||
if (e.key === "Enter") {
|
||
e.preventDefault();
|
||
addCrossClient(crossClientInput.value);
|
||
crossClientInput.value = "";
|
||
}
|
||
});
|
||
|
||
addCustomScopeBtn?.addEventListener("click", () => {
|
||
addCustomScope(customScopeInput.value);
|
||
customScopeInput.value = "";
|
||
customScopeInput.focus();
|
||
});
|
||
|
||
customScopeInput?.addEventListener("keydown", (e) => {
|
||
if (e.key === "Enter") {
|
||
e.preventDefault();
|
||
addCustomScope(customScopeInput.value);
|
||
customScopeInput.value = "";
|
||
}
|
||
});
|
||
|
||
// Device Grant Login Handler
|
||
const deviceGrantBtn = document.getElementById("device-grant-btn");
|
||
deviceGrantBtn?.addEventListener("click", async () => {
|
||
deviceGrantBtn.disabled = true;
|
||
deviceGrantBtn.textContent = "Loading...";
|
||
|
||
try {
|
||
// Collect form data similar to regular login
|
||
const form = document.getElementById("login-form");
|
||
const formData = new FormData(form);
|
||
|
||
// Get selected scopes
|
||
const scopes = formData.getAll("extra_scopes");
|
||
|
||
// Get cross-client values
|
||
const crossClients = formData.getAll("cross_client");
|
||
|
||
// Get connector_id if specified
|
||
const connectorId = formData.get("connector_id") || "";
|
||
|
||
// Initiate device flow with options
|
||
const response = await fetch('/device/login', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
scopes: scopes,
|
||
cross_clients: crossClients,
|
||
connector_id: connectorId
|
||
})
|
||
});
|
||
|
||
if (response.ok) {
|
||
// Redirect to device flow page
|
||
window.location.href = '/device';
|
||
} else {
|
||
const errorText = await response.text();
|
||
alert('Failed to start device flow: ' + errorText);
|
||
}
|
||
} catch (error) {
|
||
alert('Error starting device flow: ' + error.message);
|
||
} finally {
|
||
deviceGrantBtn.disabled = false;
|
||
deviceGrantBtn.textContent = "Device Code Flow";
|
||
}
|
||
});
|
||
})();
|
||
|