mirror of
https://github.com/renorris/openfsd
synced 2026-03-23 07:15:34 +08:00
Changes:
- Implement bootstrapping library for managing several concurrent internal services
- Refactor concurrency model for connections/logical clients and their associated I/O
- Refactor server context singleton
- Refactor error handling
- Most errors are now gracefully sent to the FSD client directly encoded as an $ER packet,
enhancing visibility and debugging
- Most errors are now rightfully treated as non-fatal
- Refactor package/dependency graph
- Refactor calling conventions/interfaces for many packages
- Refactor database package
- Refactor post office
Features:
- Add VATSIM-esque HTTP/JSON "data feed"
- Add ephemeral in-memory database option
- Add user management REST API
- Add improved web interface
- Add MySQL support (drop SQLite support)
219 lines
8.1 KiB
JavaScript
219 lines
8.1 KiB
JavaScript
function getCookie(name) {
|
|
const value = `; ${document.cookie}`;
|
|
const parts = value.split(`; ${name}=`);
|
|
if (parts.length === 2) return parts.pop().split(';').shift();
|
|
}
|
|
|
|
const showResponse = (msg) => {
|
|
$('#responseBody').text(msg);
|
|
const toast = new bootstrap.Toast($('#responseToast'));
|
|
toast.show();
|
|
};
|
|
|
|
$(document).ready(() => {
|
|
const token = getCookie("token")
|
|
|
|
const userFetchModal = $("#user-fetch-modal")
|
|
const userEditModal = $("#user-edit-modal")
|
|
const userCreateModal = $("#user-create-modal")
|
|
|
|
const userCreateStatusMsg = $("#user-create-statusmsg")
|
|
|
|
const userEditCID = $("#user-edit-cid-header")
|
|
const userEditEmail = $("#user-edit-email")
|
|
const userEditFirstname = $("#user-edit-firstname")
|
|
const userEditLastname = $("#user-edit-lastname")
|
|
const userEditNetworkRating = $("#user-edit-networkrating")
|
|
const userEditPilotRating = $("#user-edit-pilotrating")
|
|
const userEditLastUpdated = $("#user-edit-lastupdated")
|
|
const userEditCreatedAt = $("#user-edit-createdat")
|
|
|
|
const userEditPassword = $("#user-edit-password")
|
|
const userEditFSDPassword = $("#user-edit-fsdpassword")
|
|
|
|
const userEditUpdateButton = $("#user-edit-updatebutton")
|
|
const userEditDeleteButton = $("#user-edit-deletebutton")
|
|
|
|
const userCreateEmail = $("#user-create-email")
|
|
const userCreateFirstname = $("#user-create-firstname")
|
|
const userCreateLastname = $("#user-create-lastname")
|
|
const userCreateNetworkRating = $("#user-create-networkrating")
|
|
const userCreatePilotRating = $("#user-create-pilotrating")
|
|
const userCreatePassword = $("#user-create-password")
|
|
const userCreateFSDPassword = $("#user-create-fsdpassword")
|
|
|
|
const userCreateSubmitButton = $("#user-create-submitbutton")
|
|
|
|
const userFetchButton = $("#user-fetch-button")
|
|
const userCreateButton = $("#user-create-button")
|
|
|
|
const userFetchCID = $("#user-fetch-cid")
|
|
const userFetchInitiate = $("#user-fetch-initiate")
|
|
|
|
const toastClipboardButton = $("#toast-clipboard-button")
|
|
|
|
userFetchButton.click(() => {
|
|
let modal = new bootstrap.Modal(userFetchModal)
|
|
modal.show()
|
|
})
|
|
|
|
userCreateButton.click(() => {
|
|
let modal = new bootstrap.Modal(userCreateModal)
|
|
modal.show()
|
|
})
|
|
|
|
userFetchInitiate.click(() => {
|
|
new bootstrap.Modal(userFetchModal).hide()
|
|
|
|
if (userFetchCID.val() === "") {
|
|
showResponse("Error: CID empty")
|
|
return
|
|
}
|
|
|
|
new bootstrap.Modal(userFetchModal).hide()
|
|
|
|
// Fetch users
|
|
$.ajax({
|
|
type: "GET",
|
|
url: `/api/v1/users/${parseInt(userFetchCID.val())}`,
|
|
dataType: "json",
|
|
headers: {
|
|
"Authorization": `Bearer ${token}`,
|
|
},
|
|
success: function (data, textStatus, jqXHR) {
|
|
userEditCID.text(data.user.cid)
|
|
userEditEmail.val(data.user.email)
|
|
userEditFirstname.val(data.user.first_name)
|
|
userEditLastname.val(data.user.last_name)
|
|
userEditNetworkRating.val(data.user.network_rating)
|
|
userEditNetworkRating.change()
|
|
userEditPilotRating.val(data.user.pilot_rating)
|
|
userEditPilotRating.change()
|
|
userEditLastUpdated.text(data.user.updated_at)
|
|
userEditCreatedAt.text(data.user.created_at)
|
|
new bootstrap.Modal(userEditModal).show()
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
// If we received an error response from the server
|
|
showResponse('Error: ' + jqXHR.statusText + '\nMessage: ' + JSON.parse(jqXHR.responseText).msg)
|
|
}
|
|
});
|
|
})
|
|
|
|
userEditUpdateButton.click(() => {
|
|
|
|
if (!window.confirm(`Are you sure you want to update CID ${userEditCID.text()}?`)) {
|
|
return
|
|
}
|
|
|
|
// Update user
|
|
$.ajax({
|
|
type: "PUT",
|
|
url: `/api/v1/users`,
|
|
contentType: "application/json",
|
|
headers: {
|
|
"Authorization": `Bearer ${token}`,
|
|
},
|
|
data: JSON.stringify({
|
|
cid: parseInt(userEditCID.text()),
|
|
user: {
|
|
cid: parseInt(userEditCID.text()),
|
|
email: userEditEmail.val(),
|
|
first_name: userEditFirstname.val(),
|
|
last_name: userEditLastname.val(),
|
|
network_rating: parseInt(userEditNetworkRating.val()),
|
|
pilot_rating: parseInt(userEditPilotRating.val()),
|
|
password: userEditPassword.val(),
|
|
fsd_password: userEditFSDPassword.val(),
|
|
}
|
|
}),
|
|
success: function (data, textStatus, jqXHR) {
|
|
showResponse(`Successfully updated user ${userEditCID.text()}`)
|
|
new bootstrap.Modal(userEditModal).hide()
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
// If we received an error response from the server
|
|
showResponse('Error: ' + jqXHR.statusText + '\nMessage: ' + JSON.parse(jqXHR.responseText).msg)
|
|
}
|
|
});
|
|
})
|
|
|
|
userEditDeleteButton.click(() => {
|
|
|
|
if (!window.confirm(`Are you sure you want to delete CID ${userEditCID.text()}?`)) {
|
|
return
|
|
}
|
|
|
|
// Delete user
|
|
$.ajax({
|
|
type: "DELETE",
|
|
url: `/api/v1/users`,
|
|
contentType: "application/json",
|
|
headers: {
|
|
"Authorization": `Bearer ${token}`,
|
|
},
|
|
data: JSON.stringify({
|
|
cid: parseInt(userEditCID.text()),
|
|
}),
|
|
success: function (data, textStatus, jqXHR) {
|
|
showResponse(`Successfully deleted user ${userEditCID.text()}`)
|
|
new bootstrap.Modal(userEditModal).hide()
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
// If we received an error response from the server
|
|
showResponse('Error: ' + jqXHR.statusText + '\nMessage: ' + JSON.parse(jqXHR.responseText).msg)
|
|
}
|
|
});
|
|
})
|
|
|
|
userCreateSubmitButton.click(() => {
|
|
|
|
if (userCreatePassword === "" || userCreateFSDPassword === "") {
|
|
showResponse("error: password is empty")
|
|
return
|
|
}
|
|
|
|
// Create user
|
|
$.ajax({
|
|
type: "POST",
|
|
url: `/api/v1/users`,
|
|
contentType: "application/json",
|
|
headers: {
|
|
"Authorization": `Bearer ${token}`,
|
|
},
|
|
data: JSON.stringify({
|
|
user: {
|
|
email: userCreateEmail.val(),
|
|
first_name: userCreateFirstname.val(),
|
|
last_name: userCreateLastname.val(),
|
|
network_rating: parseInt(userCreateNetworkRating.val()),
|
|
pilot_rating: parseInt(userCreatePilotRating.val()),
|
|
password: userCreatePassword.val(),
|
|
fsd_password: userCreateFSDPassword.val(),
|
|
}
|
|
}),
|
|
success: function (data, textStatus, jqXHR) {
|
|
|
|
let pwdMsg = userCreatePassword.val() === "" ? `\nPassword: ${data.user.password}` : ``
|
|
userCreateFSDPassword.val() === "" ? pwdMsg += `\nFSD Password: ${data.user.fsd_password}` : ``
|
|
|
|
showResponse(`Successfully created user: CID = ${data.user.cid}\n${pwdMsg}`)
|
|
new bootstrap.Modal(userCreateModal).hide()
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
// If we received an error response from the server
|
|
showResponse('Error: ' + jqXHR.statusText + '\nMessage: ' + JSON.parse(jqXHR.responseText).msg)
|
|
}
|
|
});
|
|
})
|
|
|
|
toastClipboardButton.click(() => {
|
|
let text = $("#responseBody").text()
|
|
navigator.clipboard.writeText(text).then(r => {
|
|
$("#toast-copy-banner").text("Copied!")
|
|
setTimeout(() => {
|
|
$("#toast-copy-banner").text("")
|
|
}, 2000)
|
|
});
|
|
})
|
|
}) |