247 lines
8.1 KiB
JavaScript
247 lines
8.1 KiB
JavaScript
/*Canopy - The next generation of stoner streaming software
|
|
Copyright (C) 2024 Rainbownapkin and the TTN Community
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
|
|
|
class canopyAdminUtils{
|
|
constructor(){
|
|
|
|
}
|
|
|
|
async setUserRank(user, rank){
|
|
var response = await fetch(`/api/admin/changeRank`,{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
//Unfortunately JSON doesn't natively handle ES6 maps, and god forbid someone update the standard in a way that's backwards compatible...
|
|
body: JSON.stringify({user, rank})
|
|
});
|
|
|
|
if(response.status == 200){
|
|
return await response.json();
|
|
}else{
|
|
utils.ux.displayResponseError(await response.json());
|
|
}
|
|
}
|
|
|
|
async setPermission(permMap){
|
|
var response = await fetch(`/api/admin/permissions`,{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
//Unfortunately JSON doesn't natively handle ES6 maps, and god forbid someone update the standard in a way that's backwards compatible...
|
|
body: JSON.stringify({permissionsMap: Object.fromEntries(permMap)})
|
|
});
|
|
|
|
if(response.status == 200){
|
|
return await response.json();
|
|
}else{
|
|
utils.ux.displayResponseError(await response.json());
|
|
}
|
|
}
|
|
|
|
async setChannelOverride(permMap){
|
|
var response = await fetch(`/api/admin/permissions`,{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
//Unfortunately JSON doesn't natively handle ES6 maps, and god forbid someone update the standard in a way that's backwards compatible...
|
|
body: JSON.stringify({channelPermissionsMap: Object.fromEntries(permMap)})
|
|
});
|
|
|
|
if(response.status == 200){
|
|
return await response.json();
|
|
}else{
|
|
utils.ux.displayResponseError(await response.json());
|
|
}
|
|
}
|
|
|
|
async getBans(){
|
|
var response = await fetch(`/api/admin/ban`,{
|
|
method: "GET"
|
|
});
|
|
|
|
if(response.status == 200){
|
|
return await response.json();
|
|
}else{
|
|
utils.ux.displayResponseError(await response.json());
|
|
}
|
|
}
|
|
|
|
async banUser(user){
|
|
var response = await fetch(`/api/admin/ban`,{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
//Unfortunately JSON doesn't natively handle ES6 maps, and god forbid someone update the standard in a way that's backwards compatible...
|
|
body: JSON.stringify({user})
|
|
});
|
|
|
|
if(response.status == 200){
|
|
return await response.json();
|
|
}else{
|
|
utils.ux.displayResponseError(await response.json());
|
|
}
|
|
}
|
|
}
|
|
|
|
class adminUserList{
|
|
constructor(){
|
|
this.rankSelectors = document.querySelectorAll(".admin-user-list-rank-select");
|
|
|
|
this.setupInput();
|
|
}
|
|
|
|
setupInput(){
|
|
this.rankSelectors.forEach((rankSelector)=>{
|
|
rankSelector.addEventListener("change", this.setRank.bind(this))
|
|
});
|
|
}
|
|
|
|
async setRank(event){
|
|
const user = event.target.id.replace("admin-user-list-rank-select-","");
|
|
const rank = event.target.value;
|
|
|
|
this.updateSelect(await adminUtil.setUserRank(user, rank), event.target);
|
|
}
|
|
|
|
updateSelect(update, select){
|
|
if(update != null){
|
|
select.value = update.rank;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class adminPermissionList{
|
|
constructor(){
|
|
this.permissionSelectors = document.querySelectorAll(".admin-perm-list-rank-select");
|
|
this.channelPermissionSelectors = document.querySelectorAll(".admin-chan-perm-list-rank-select");
|
|
|
|
this.setupInput();
|
|
}
|
|
|
|
setupInput(){
|
|
this.permissionSelectors.forEach((permissionSelector)=>{
|
|
permissionSelector.addEventListener("change", this.setPerm.bind(this))
|
|
});
|
|
|
|
this.channelPermissionSelectors.forEach((permissionSelector)=>{
|
|
permissionSelector.addEventListener("change", this.setChanPerm.bind(this))
|
|
});
|
|
}
|
|
|
|
async setPerm(event){
|
|
const permMap = new Map([[event.target.id.replace("admin-perm-list-rank-select-",""), event.target.value]]);
|
|
|
|
this.updateSelect(await adminUtil.setPermission(permMap), event.target);
|
|
}
|
|
|
|
async setChanPerm(event){
|
|
const permMap = new Map([[event.target.id.replace("admin-chan-perm-list-rank-select-",""), event.target.value]]);
|
|
|
|
this.updateChanSelect(await adminUtil.setChannelOverride(permMap), event.target);
|
|
}
|
|
|
|
updateSelect(update, select){
|
|
if(update != null){
|
|
var perm = select.id.replace("admin-perm-list-rank-select-","");
|
|
|
|
select.value = update[perm];
|
|
}
|
|
}
|
|
|
|
updateChanSelect(update, select){
|
|
if(update != null){
|
|
var perm = select.id.replace("admin-chan-perm-list-rank-select-","");
|
|
|
|
select.value = update.channelOverrides[perm];
|
|
}
|
|
}
|
|
}
|
|
|
|
class adminUserBanList{
|
|
constructor(){
|
|
this.table = document.querySelector("#admin-ban-list-table");
|
|
|
|
this.getBanList();
|
|
}
|
|
|
|
async getBanList(){
|
|
this.renderBanList(await adminUtil.getBans());
|
|
}
|
|
|
|
renderBanList(banList){
|
|
banList.forEach((ban) => {
|
|
//Create entry row
|
|
const entryRow = document.createElement('tr');
|
|
entryRow.classList.add("admin-list-entry");
|
|
|
|
//Create IMG node inside of IMG cell
|
|
const imgNode = document.createElement('img');
|
|
imgNode.classList.add("admin-list-entry","admin-list-entry-item");
|
|
imgNode.src = ban.user.img;
|
|
|
|
console.log(new Date(ban.user.date).toDateString());
|
|
|
|
const expirationDate = new Date(ban.expirationDate);
|
|
|
|
const expirationDays = Math.floor((expirationDate - new Date()) / (1000 * 60 * 60 * 24));
|
|
|
|
//Append cells to row
|
|
entryRow.appendChild(newCell(imgNode, true, true));
|
|
entryRow.appendChild(newCell(ban.user.id));
|
|
entryRow.appendChild(newCell(ban.user.user));
|
|
entryRow.appendChild(newCell(new Date(ban.user.date).toDateString()));
|
|
entryRow.appendChild(newCell(new Date(ban.banDate).toDateString()));
|
|
entryRow.appendChild(newCell(`${expirationDate.toDateString()} (${expirationDays} days left)`));
|
|
entryRow.appendChild(newCell(ban.deleteAccountOnExpire ? "Delete" : "Un-Ban"));
|
|
|
|
//Append row to table
|
|
this.table.appendChild(entryRow);
|
|
});
|
|
|
|
function newCell(content, addAsNode = false, firstCol = false){
|
|
//Create a new 'td' element
|
|
const cell = document.createElement('td');
|
|
cell.classList.add("admin-list-entry","admin-list-entry-item");
|
|
|
|
//If it's not the first column, mention it!
|
|
if(!firstCol){
|
|
cell.classList.add("admin-list-entry-not-first-col");
|
|
}
|
|
|
|
//If we're adding as node
|
|
if(addAsNode){
|
|
//append it like it's a node
|
|
cell.appendChild(content);
|
|
}else{
|
|
//otherwise use it as innerHTML
|
|
cell.innerHTML = content;
|
|
}
|
|
|
|
//return the resulting cell
|
|
return cell;
|
|
}
|
|
}
|
|
}
|
|
|
|
const adminUtil = new canopyAdminUtils();
|
|
const userList = new adminUserList();
|
|
const permissionList = new adminPermissionList();
|
|
const userBanList = new adminUserBanList(); |