diff --git a/Config.ts b/Config.ts index ba970ef..62d8506 100644 --- a/Config.ts +++ b/Config.ts @@ -1,3 +1,3 @@ export const Config = { - APIEndpoint: "https://auth.collabvm.org" + APIEndpoint: "http://127.0.0.1:5858" }; \ No newline at end of file diff --git a/src/html/index.html b/src/html/index.html index 15b9647..66d7763 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -80,7 +80,8 @@ Username Email Rank - Banned + Banned? + Ban Reason Date of Birth Created At Registration IP diff --git a/src/ts/AuthManager.ts b/src/ts/AuthManager.ts index 980c07a..db57344 100644 --- a/src/ts/AuthManager.ts +++ b/src/ts/AuthManager.ts @@ -129,6 +129,26 @@ export default class AuthManager { }); } + setUserBan(username : string, banned : boolean, reason : string | undefined = undefined) { + return new Promise(async res => { + if (!this.account) throw new Error("Cannot ban/unban without logging in first"); + var data = await fetch(this.apiEndpoint + "/api/v1/admin/ban", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + token: this.account.sessionToken, + username: username, + banned: banned, + reason: reason + }) + }); + var json = await data.json() as BanResult; + res(json); + }); + } + listBots(resultsPerPage : number, page : number, owner : string | undefined) { return new Promise(async res => { var data = await fetch(this.apiEndpoint + "/api/v1/bots/list", { @@ -233,6 +253,7 @@ export interface User { email : string; rank : number; banned : boolean; + banReason : string; dateOfBirth : string; dateJoined : string; registrationIp : string; @@ -275,4 +296,9 @@ export interface CreateBotResult { export interface AdminUpdateBotResult { success : boolean; error : string | undefined; +} + +export interface BanResult { + success : boolean; + error : string | undefined; } \ No newline at end of file diff --git a/src/ts/main.ts b/src/ts/main.ts index 44558c6..bf4faab 100644 --- a/src/ts/main.ts +++ b/src/ts/main.ts @@ -61,35 +61,33 @@ var hcaptchaid : string; elements.adminLoginForm.addEventListener('submit', async e => { e.preventDefault(); - if (auth.info!.hcaptcha.required) { - var hcaptchaToken = undefined; - if (auth!.info!.hcaptcha.required) { - var response = hcaptcha.getResponse(hcaptchaid); - if (response === "") { - alert("Missing captcha!"); + var hcaptchaToken = undefined; + if (auth!.info!.hcaptcha.required) { + var response = hcaptcha.getResponse(hcaptchaid); + if (response === "") { + alert("Missing captcha!"); + return false; + } + hcaptchaToken = response; + } + var result = await auth.login(elements.loginUsername.value, elements.loginPassword.value, hcaptchaToken); + elements.loginUsername.value = ""; + elements.loginPassword.value = ""; + if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaid); + if (result.success) { + if (result.rank !== 2 && result.rank !== 3) { + if (!result.developer) { + alert("You have no power here!"); + await auth.logout(); return false; } - hcaptchaToken = response; - } - var result = await auth.login(elements.loginUsername.value, elements.loginPassword.value, hcaptchaToken); - elements.loginUsername.value = ""; - elements.loginPassword.value = ""; - hcaptcha.reset(hcaptchaid); - if (result.success) { - if (result.rank !== 2) { - if (!result.developer) { - alert("You have no power here!"); - await auth.logout(); - return false; - } - elements.usersNavLink.style.display = "none"; - loadBotsView(); - } else loadUsersView(); - localStorage.setItem(`collabvm_session_${new URL(Config.APIEndpoint).host}`, result.token!); - loadAdminView(); - } else { - alert("Login failed: " + result.error); - } + elements.usersNavLink.style.display = "none"; + loadBotsView(); + } else loadUsersView(); + localStorage.setItem(`collabvm_session_${new URL(Config.APIEndpoint).host}`, result.token!); + loadAdminView(); + } else { + alert("Login failed: " + result.error); } return false; }); @@ -133,26 +131,57 @@ elements.searchUsersForm.addEventListener('submit', async e => { cell.innerText = user.email; cell = row.insertCell(); // Rank dropdown - var rankSelect = document.createElement('select'); - rankSelect.classList.add('form-select'); - rankSelect.innerHTML = ``; - rankSelect.value = user.rank.toString(10); - rankSelect.addEventListener('change', async e => { - var newRank = parseInt(rankSelect.value); + if (auth.account!.rank === 2) { + var rankSelect = document.createElement('select'); + rankSelect.classList.add('form-select'); + rankSelect.innerHTML = ``; + rankSelect.value = user.rank.toString(10); + rankSelect.addEventListener('change', async e => { + var newRank = parseInt(rankSelect.value); + // @ts-ignore + if (!window.confirm(`Are you sure you want to set ${user.username}'s rank to ${RankString[newRank]}?`)) { + e.preventDefault(); + rankSelect.value = user.rank.toString(10); + return false; + } + var result = await auth.updateUser(user.username, newRank); + if (!result.success) { + alert("Failed to set rank: " + result.error); + } + }); + cell.appendChild(rankSelect); + } else { // @ts-ignore - if (!window.confirm(`Are you sure you want to set ${user.username}'s rank to ${RankString[newRank]}?`)) { - e.preventDefault(); - rankSelect.value = user.rank.toString(10); - return false; - } - var result = await auth.updateUser(user.username, newRank); - if (!result.success) { - alert("Failed to set rank: " + result.error); + cell.innerText = RankString[user.rank]; + } + cell = row.insertCell(); + var bannedCheckbox = document.createElement('input'); + bannedCheckbox.type = 'checkbox'; + bannedCheckbox.checked = user.banned; + bannedCheckbox.addEventListener('change', async e => { + var banned = bannedCheckbox.checked; + if (banned) { + var reason = window.prompt(`Enter a reason for banning ${user.username}:`); + if (reason === null || reason === "") { + e.preventDefault(); + bannedCheckbox.checked = false; + return false; + } + await auth.setUserBan(user.username, true, reason); + banReasonCell.innerText = reason; + } else { + if (!window.confirm(`Are you sure you want to unban ${user.username}?`)) { + e.preventDefault(); + bannedCheckbox.checked = true; + return false; + } + await auth.setUserBan(user.username, false); + banReasonCell.innerText = ""; } }); - cell.appendChild(rankSelect); - cell = row.insertCell(); - cell.innerText = user.banned ? "Yes" : "No"; + cell.appendChild(bannedCheckbox); + var banReasonCell = row.insertCell(); + banReasonCell.innerText = user.banReason; cell = row.insertCell(); cell.innerText = user.dateOfBirth; cell = row.insertCell(); @@ -220,10 +249,10 @@ elements.searchBotsForm.addEventListener('submit', async e => { cell = row.insertCell(); cell.innerText = bot.username; cell = row.insertCell(); - if (auth!.account!.rank === 2) { + if (auth!.account!.rank === 2 || auth!.account!.username === bot.owner) { var rankSelect = document.createElement('select'); rankSelect.classList.add('form-select'); - rankSelect.innerHTML = ``; + rankSelect.innerHTML = `${auth!.account!.rank === 2 && ``}`; rankSelect.value = bot.rank.toString(10); rankSelect.addEventListener('change', async e => { var newRank = parseInt(rankSelect.value); @@ -286,7 +315,7 @@ elements.createBotForm.addEventListener('submit', async e => { if (token) { var session = await auth.loadSession(token); if (session.success) { - if (session.rank! !== 2) { + if (session.rank! !== 2 && session.rank! !== 3) { if (!session.developer) { await auth.logout(); localStorage.removeItem(`collabvm_session_${new URL(Config.APIEndpoint).host}`);