Files
gaseous-server/gaseous-server/wwwroot/pages/settings/users.js
2024-09-01 01:00:54 +10:00

590 lines
26 KiB
JavaScript

function SetupPage() {
// set up new user button
let newUserButton = document.getElementById('settings_users_new');
newUserButton.addEventListener('click', function () {
let userNew = new UserNew();
userNew.open();
});
}
function GetUsers() {
console.log("Loading users...");
let targetDiv = document.getElementById('settings_users_table_container');
targetDiv.innerHTML = '';
ajaxCall(
'/api/v1.1/Account/Users',
'GET',
function (result) {
let newTable = document.createElement('table');
newTable.className = 'romtable';
newTable.style.width = '100%';
newTable.cellSpacing = 0;
newTable.appendChild(
createTableRow(
true,
[
'',
'Email',
'Role',
'Age Restriction',
''
],
'',
''
)
);
for (let i = 0; i < result.length; i++) {
let userAvatar = new Avatar(result[i].profileId, 32, 32, true);
userAvatar.classList.add("user_list_icon");
let roleDiv = document.createElement('div');
let roleItem = CreateBadge(result[i].highestRole);
roleDiv.appendChild(roleItem);
let ageRestrictionPolicyDescription = document.createElement('div');
if (result[i].securityProfile != null) {
if (result[i].securityProfile.ageRestrictionPolicy != null) {
let IncludeUnratedText = '';
if (result[i].securityProfile.ageRestrictionPolicy.includeUnrated == true) {
IncludeUnratedText = " &#43; Unclassified titles";
}
let restrictionText = result[i].securityProfile.ageRestrictionPolicy.maximumAgeRestriction + IncludeUnratedText;
ageRestrictionPolicyDescription = CreateBadge(restrictionText);
}
}
let controls = document.createElement('div');
controls.style.textAlign = 'right';
let editButton = '';
let deleteButton = '';
if (userProfile.userId != result[i].id) {
editButton = document.createElement('a');
editButton.href = '#';
editButton.addEventListener('click', () => {
// showDialog('settingsuseredit', result[i].id);
let userEdit = new UserEdit(result[i].id, GetUsers);
userEdit.open();
});
editButton.classList.add('romlink');
let editButtonImage = document.createElement('img');
editButtonImage.src = '/images/edit.svg';
editButtonImage.classList.add('banner_button_image');
editButtonImage.alt = 'Edit';
editButtonImage.title = 'Edit';
editButton.appendChild(editButtonImage);
controls.appendChild(editButton);
deleteButton = document.createElement('a');
deleteButton.href = '#';
deleteButton.addEventListener('click', () => {
let warningDialog = new MessageBox("Delete User", "Are you sure you want to delete this user?<br /><br /><strong>Warning</strong>: This cannot be undone!");
warningDialog.addButton(new ModalButton("OK", 2, warningDialog, async (callingObject) => {
fetch("/api/v1.1/Account/Users/" + result[i].id, {
method: 'DELETE'
}).then(async response => {
if (response.ok) {
GetUsers();
callingObject.msgDialog.close();
} else {
let result = await response.json();
let warningDialog = new MessageBox("Delete User Error", "An error occurred while deleting the user.");
warningDialog.open();
}
});
}));
warningDialog.addButton(new ModalButton("Cancel", 0, warningDialog, async (callingObject) => {
callingObject.msgDialog.close();
}));
warningDialog.open();
});
deleteButton.classList.add('romlink');
let deleteButtonImage = document.createElement('img');
deleteButtonImage.src = '/images/delete.svg';
deleteButtonImage.classList.add('banner_button_image');
deleteButtonImage.alt = 'Delete';
deleteButtonImage.title = 'Delete';
deleteButton.appendChild(deleteButtonImage);
controls.appendChild(deleteButton);
}
newTable.appendChild(
createTableRow(
false,
[
userAvatar,
result[i].emailAddress,
roleDiv,
ageRestrictionPolicyDescription,
controls
],
'romrow',
'romcell'
)
);
}
targetDiv.appendChild(newTable);
}
);
}
class UserNew {
constructor() {
}
async open() {
// Create the modal
this.dialog = await new Modal("usernew");
await this.dialog.BuildModal();
// setup the dialog
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = "New User";
this.dialog.modalElement.style = 'width: 550px; height: 380px; min-width: unset; min-height: unset; max-width: unset; max-height: unset;';
// setup email check
this.email = this.dialog.modalElement.querySelector('#email-address');
this.email_error = this.dialog.modalElement.querySelector('#email-error');
this.EmailCheck = new EmailCheck(this.email, this.email_error);
// setup password check
this.password_new = this.dialog.modalElement.querySelector('#new-password');
this.password_confirm = this.dialog.modalElement.querySelector('#confirm-new-password');
this.password_error = this.dialog.modalElement.querySelector('#password-error');
this.PasswordCheck = new PasswordCheck(this.password_new, this.password_confirm, this.password_error);
// add the ok button
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
if (!await EmailCheck.CheckEmail(callingObject.EmailCheck, callingObject.email)) {
// display an error
let warningDialog = new MessageBox("New User Error", "Invalid email address. Please correct the errors before continuing.");
warningDialog.open();
return;
}
if (!PasswordCheck.CheckPasswords(callingObject.PasswordCheck, callingObject.password_new, callingObject.password_confirm)) {
// display an error
let warningDialog = new MessageBox("New User Error", "The password doesn't meet the requirements. Please correct the errors before continuing.");
warningDialog.open();
return;
}
// create the new user
var model = {
"userName": callingObject.email.value,
"email": callingObject.email.value,
"password": callingObject.password_new.value,
"confirmPassword": callingObject.password_confirm.value
}
fetch("/api/v1.1/Account/Users", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(model)
}).then(async response => {
if (response.ok) {
let result = await response.json();
GetUsers();
callingObject.dialog.close();
} else {
let result = await response.json();
let warningDialog = new MessageBox("New User Error", "An error occurred while creating the user. Check that the email address is valid and the password meets the requirements.");
warningDialog.open();
}
});
});
this.dialog.addButton(okButton);
// add the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, async function (callingObject) {
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// show the dialog
await this.dialog.open();
}
}
class UserEdit {
constructor(UserId, OkCallback, CancelCallback) {
this.userId = UserId;
this.okCallback = OkCallback;
this.cancelCallback = CancelCallback;
}
async open() {
// Create the modal
this.dialog = await new Modal("useredit");
await this.dialog.BuildModal();
await fetch("/api/v1.1/Account/Users/" + this.userId, {
method: 'GET'
}).then(async response => {
if (response.ok) {
let result = await response.json();
this.user = result;
} else {
let result = await response.json();
let warningDialog = new MessageBox("Edit User Error", "An error occurred while retrieving the user.");
warningDialog.open();
}
});
// setup the dialog
if (this.user.profileId == "00000000-0000-0000-0000-000000000000") {
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.user.emailAddress;
} else {
await fetch("/api/v1.1/UserProfile/" + this.user.profileId, {
method: 'GET'
}).then(async response => {
if (response.ok) {
let result = await response.json();
this.profile = result;
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.profile.displayName + ' (' + this.user.emailAddress + ')';
} else {
this.dialog.modalElement.querySelector('#modal-header-text').innerHTML = this.user.emailAddress;
}
});
}
// setup general page
this.dialog.modalElement.querySelector('#user-id').innerHTML = this.user.id;
let userProfileCard = new ProfileCard(this.user.profileId, true);
if (this.user.lockoutEnabled === true) {
this.dialog.modalElement.querySelector('#user-lockedout').innerHTML = 'Locked';
this.dialog.modalElement.querySelector('#user-lockedout').style.backgroundColor = 'red';
this.dialog.modalElement.querySelector('#user-lockedout-end').innerHTML = 'until ' + new Date(this.user.lockoutEnd).toLocaleString();
} else {
this.dialog.modalElement.querySelector('#user-lockedout').innerHTML = 'Unlocked';
this.dialog.modalElement.querySelector('#user-lockedout').style.backgroundColor = '';
this.dialog.modalElement.querySelector('#user-lockedout-end').innerHTML = '';
}
this.dialog.modalElement.querySelector('#user-profile-card').appendChild(userProfileCard);
// set user role
this.role_Player = this.dialog.modalElement.querySelector('#settings_user_role_player');
this.role_Player.addEventListener('change', () => {
this.UpdateRolePermissionsDisplay();
});
this.role_Gamer = this.dialog.modalElement.querySelector('#settings_user_role_gamer');
this.role_Gamer.addEventListener('change', () => {
this.UpdateRolePermissionsDisplay();
});
this.role_Admin = this.dialog.modalElement.querySelector('#settings_user_role_admin');
this.role_Admin.addEventListener('change', () => {
this.UpdateRolePermissionsDisplay();
});
this.dialog.modalElement.querySelector('#settings_user_role_' + this.user.highestRole.toLowerCase()).checked = true;
this.UpdateRolePermissionsDisplay();
this.rolePermTable = this.dialog.modalElement.querySelector('#role-permissions-table');
this.rolePermCover = this.dialog.modalElement.querySelector('#role-permissions-expand');
this.rolePermLink = this.dialog.modalElement.querySelector('#role-permissions-expand-link');
this.rolePermLink.addEventListener('click', () => {
if (Array.from(this.rolePermTable.classList).includes('collapsed')) {
this.rolePermTable.classList.remove('collapsed');
this.rolePermTable.classList.add('expanded');
this.rolePermCover.classList.remove('collapsed');
this.rolePermCover.classList.add('expanded');
this.rolePermLink.innerHTML = 'Hide details...';
} else {
this.rolePermTable.classList.remove('expanded');
this.rolePermTable.classList.add('collapsed');
this.rolePermCover.classList.remove('expanded');
this.rolePermCover.classList.add('collapsed');
this.rolePermLink.innerHTML = 'Show details...';
}
});
// setup age restriction tab
let ageRestrictionPolicyBox = this.dialog.modalElement.querySelector('#settings_user_agerestrictions');
let ageRestrictionPolicyTable = document.createElement('table');
for (let ageGroup in AgeRatingGroups) {
let tRow = document.createElement('tr');
let tCell = document.createElement('td');
let ageGroupRadio = document.createElement('input');
ageGroupRadio.type = 'radio';
ageGroupRadio.name = 'ageGroup';
ageGroupRadio.value = ageGroup;
ageGroupRadio.id = 'ageGroup_' + ageGroup;
ageGroupRadio.addEventListener('change', () => {
this.UpdateAssignedAgeGroupDisplay();
});
tCell.appendChild(ageGroupRadio);
let ageGroupLabel = document.createElement('label');
ageGroupLabel.htmlFor = 'ageGroup_' + ageGroup;
ageGroupLabel.innerHTML = ageGroup;
tCell.appendChild(ageGroupLabel);
tRow.appendChild(tCell);
ageRestrictionPolicyTable.appendChild(tRow);
}
// add allow unclassified titles checkbox
let tRow = document.createElement('tr');
let tCell = document.createElement('td');
let includeUnratedCheckbox = document.createElement('input');
includeUnratedCheckbox.type = 'checkbox';
includeUnratedCheckbox.id = 'includeUnrated';
includeUnratedCheckbox.addEventListener('change', () => {
this.UpdateAssignedAgeGroupDisplay();
});
tCell.appendChild(includeUnratedCheckbox);
let includeUnratedLabel = document.createElement('label');
includeUnratedLabel.htmlFor = 'includeUnrated';
includeUnratedLabel.innerHTML = 'Include unrated titles';
tCell.appendChild(includeUnratedLabel);
tRow.appendChild(tCell);
ageRestrictionPolicyTable.appendChild(tRow);
ageRestrictionPolicyBox.appendChild(ageRestrictionPolicyTable);
this.dialog.modalElement.querySelector('#ageGroup_' + this.user.securityProfile.ageRestrictionPolicy.maximumAgeRestriction).checked = true;
if (this.user.securityProfile.ageRestrictionPolicy.includeUnrated === true) {
this.dialog.modalElement.querySelector('#includeUnrated').checked = true;
}
this.UpdateAssignedAgeGroupDisplay();
this.agePermTable = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_preview');
this.agePermCover = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_expand');
this.agePermLink = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_expand-link');
this.agePermLink.addEventListener('click', () => {
if (Array.from(this.agePermTable.classList).includes('collapsed')) {
this.agePermTable.classList.remove('collapsed');
this.agePermTable.classList.add('expanded');
this.agePermCover.classList.remove('collapsed');
this.agePermCover.classList.add('expanded');
this.agePermLink.innerHTML = 'Hide details...';
} else {
this.agePermTable.classList.remove('expanded');
this.agePermTable.classList.add('collapsed');
this.agePermCover.classList.remove('expanded');
this.agePermCover.classList.add('collapsed');
this.agePermLink.innerHTML = 'Show details...';
}
});
// set up the password change form
this.password_new = this.dialog.modalElement.querySelector('#new-password');
this.password_confirm = this.dialog.modalElement.querySelector('#confirm-new-password');
this.password_error = this.dialog.modalElement.querySelector('#password-error');
this.PasswordCheck = new PasswordCheck(this.password_new, this.password_confirm, this.password_error);
// create the ok button
let okButton = new ModalButton("OK", 1, this, async function (callingObject) {
// check if a new password has been entered
if (callingObject.password_new.value.length > 0 && callingObject.password_confirm.value.length > 0) {
// check if the new password meets the rules
if (!PasswordCheck.CheckPasswords(callingObject.PasswordCheck, callingObject.password_new, callingObject.password_confirm)) {
// display an error
let warningDialog = new MessageBox("Password Reset Error", "The new password does not meet the requirements.");
warningDialog.open();
return;
}
// requirements met, reset the password
let model = {
newPassword: callingObject.password_new.value,
confirmPassword: callingObject.password_confirm.value
};
let changeSuccessfull = false;
await fetch("/api/v1.1/Account/Users/" + callingObject.userId + "/Password", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(model)
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating password:");
console.error(response);
let warningDialog = new MessageBox("Password Reset Error", "The password reset failed. Check the current password and try again.");
warningDialog.open();
changeSuccessfull = false;
return;
} else {
// clear the password fields
callingObject.password_new.value = "";
callingObject.password_confirm.value = "";
callingObject.password_error.innerHTML = "";
changeSuccessfull = true;
}
});
if (changeSuccessfull == false) {
return;
}
}
// set the role
let selectedRole = callingObject.dialog.modalElement.querySelector('input[name="settings_user_role"]:checked').value.toLowerCase();
await fetch("/api/v1.1/Account/Users/" + callingObject.userId + "/Roles?RoleName=" + selectedRole, {
method: 'POST'
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating role:");
console.error(response);
let warningDialog = new MessageBox("Role Update Error", "The role update failed. Check the role and try again.");
warningDialog.open();
return;
}
});
// set the security profile
let securityProfile = {
"ageRestrictionPolicy": {
"maximumAgeRestriction": callingObject.dialog.modalElement.querySelector('input[name="ageGroup"]:checked').value,
"includeUnrated": callingObject.dialog.modalElement.querySelector('#includeUnrated').checked
}
};
await fetch("/api/v1.1/Account/Users/" + callingObject.userId + "/SecurityProfile", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(securityProfile)
}).then(async response => {
if (!response.ok) {
// handle the error
console.error("Error updating security profile:");
console.error(response);
let warningDialog = new MessageBox("Security Profile Update Error", "The security profile update failed. Check the settings and try again.");
warningDialog.open();
return;
}
});
if (callingObject.okCallback) {
callingObject.okCallback();
}
callingObject.dialog.close();
});
this.dialog.addButton(okButton);
// create the cancel button
let cancelButton = new ModalButton("Cancel", 0, this, function (callingObject) {
if (callingObject.cancelCallback) {
callingObject.cancelCallback();
}
callingObject.dialog.close();
});
this.dialog.addButton(cancelButton);
// show the dialog
this.dialog.open();
}
UpdateRolePermissionsDisplay() {
// get selected role
let selectedRole = this.dialog.modalElement.querySelector('input[name="settings_user_role"]:checked').value.toLowerCase();
// get the player role icons
let playerPermssions = this.dialog.modalElement.querySelectorAll('td[name="role-player"]');
playerPermssions.forEach(element => {
if (selectedRole == 'player') {
element.style.display = '';
} else {
element.style.display = 'none';
}
});
// get the gamer role icons
let gamerPermssions = this.dialog.modalElement.querySelectorAll('td[name="role-gamer"]');
gamerPermssions.forEach(element => {
if (selectedRole == 'gamer') {
element.style.display = '';
} else {
element.style.display = 'none';
}
});
// get the admin role icons
let adminPermssions = this.dialog.modalElement.querySelectorAll('td[name="role-admin"]');
adminPermssions.forEach(element => {
if (selectedRole == 'admin') {
element.style.display = '';
} else {
element.style.display = 'none';
}
});
}
UpdateAssignedAgeGroupDisplay() {
// get the selected age group
let selectedAgeGroup = this.dialog.modalElement.querySelector('input[name="ageGroup"]:checked').value;
let ageGroupList = [];
switch (selectedAgeGroup) {
case "Adult":
ageGroupList = ["Child", "Teen", "Mature", "Adult"];
break;
case "Mature":
ageGroupList = ["Child", "Teen", "Mature"];
break;
case "Teen":
ageGroupList = ["Child", "Teen"];
break;
case "Child":
ageGroupList = ["Child"];
break;
default:
break;
}
// get target div
let assignedAgeGroup = this.dialog.modalElement.querySelector('#settings_user_agerestrictions_preview');
assignedAgeGroup.innerHTML = '';
// generate restrictions table
let ageRestrictionPolicyTable = document.createElement('table');
ageRestrictionPolicyTable.classList.add('romtable');
ageRestrictionPolicyTable.setAttribute('cellspacing', '0');
for (const [key, value] of Object.entries(ClassificationBoards)) {
let thRow = document.createElement('tr');
let thCell = document.createElement('th');
thCell.innerHTML = value;
thRow.appendChild(thCell);
ageRestrictionPolicyTable.appendChild(thRow);
// add age rating icons
let trRow = document.createElement('tr');
let tdCell = document.createElement('td');
for (let i = 0; i < ageGroupList.length; i++) {
let ageRatingBadgeIndexes = AgeRatingGroups[ageGroupList[i]][key];
for (let j = 0; j < ageRatingBadgeIndexes.length; j++) {
let ageRatingBatch = document.createElement('img');
ageRatingBatch.src = '/images/Ratings/' + key + '/' + AgeRatingStrings[ageRatingBadgeIndexes[j]] + '.svg';
ageRatingBatch.classList.add('rating_image_mini');
ageRatingBatch.setAttribute('title', ClassificationRatings[AgeRatingStrings[ageRatingBadgeIndexes[j]]]);
tdCell.appendChild(ageRatingBatch);
}
ageRestrictionPolicyTable.appendChild(trRow);
}
trRow.appendChild(tdCell);
ageRestrictionPolicyTable.appendChild(trRow);
}
assignedAgeGroup.appendChild(ageRestrictionPolicyTable);
}
}