🎉 bump to alpha

This commit is contained in:
May 2023-08-01 14:50:28 +00:00
parent a5404ecc13
commit 28c066e1fc
4 changed files with 171 additions and 9 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "monofile", "name": "monofile",
"version": "1.3.0-pa", "version": "1.3.0-alpha",
"description": "Discord-based file sharing", "description": "Discord-based file sharing",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View file

@ -4,6 +4,7 @@ import * as Accounts from "../lib/accounts";
import * as auth from "../lib/auth"; import * as auth from "../lib/auth";
import bytes from "bytes" import bytes from "bytes"
import {writeFile} from "fs"; import {writeFile} from "fs";
import { sendMail } from "../lib/mail";
import ServeError from "../lib/errors"; import ServeError from "../lib/errors";
import Files from "../lib/files"; import Files from "../lib/files";
@ -67,6 +68,36 @@ adminRoutes.post("/reset", parser, (req,res) => {
}) })
adminRoutes.post("/elevate", parser, (req,res) => {
if (!auth.validate(req.cookies.auth)) {
ServeError(res, 401, "not logged in")
return
}
let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account
if (!acc) return
if (!acc.admin) return
if (typeof req.body.target !== "string") {
res.status(404)
res.send()
return
}
let targetAccount = Accounts.getFromUsername(req.body.target)
if (!targetAccount) {
res.status(404)
res.send()
return
}
targetAccount.admin = true;
Accounts.save()
res.send()
})
adminRoutes.post("/delete", parser, (req,res) => { adminRoutes.post("/delete", parser, (req,res) => {
if (!auth.validate(req.cookies.auth)) { if (!auth.validate(req.cookies.auth)) {
@ -100,6 +131,55 @@ adminRoutes.post("/delete", parser, (req,res) => {
}) })
adminRoutes.post("/delete_account", parser, async (req,res) => {
if (!auth.validate(req.cookies.auth)) {
ServeError(res, 401, "not logged in")
return
}
let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account
if (!acc) return
if (!acc.admin) return
if (typeof req.body.target !== "string") {
res.status(404)
res.send()
return
}
let targetAccount = Accounts.getFromUsername(req.body.target)
if (!targetAccount) {
res.status(404)
res.send()
return
}
let accId = targetAccount.id
auth.AuthTokens.filter(e => e.account == accId).forEach((v) => {
auth.invalidate(v.token)
})
let cpl = () => Accounts.deleteAccount(accId).then(_ => {
if (targetAccount?.email) {
sendMail(targetAccount.email, "Notice of account deletion", `Your account, <span username>${targetAccount.username}</span>, has been deleted by <span username>${acc.username}</span> for the following reason: <br><br><span style="font-weight:600">${req.body.reason || "(no reason specified)"}</span><br><br> Your files ${req.body.deleteFiles ? "have been deleted" : "have not been modified"}. Thank you for using monofile.`)
}
res.send("account deleted")
})
if (req.body.deleteFiles) {
let f = targetAccount.files.map(e=>e) // make shallow copy so that iterating over it doesnt Die
for (let v of f) {
files.unlink(v,true).catch(err => console.error(err))
}
writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => {
if (err) console.log(err)
cpl()
})
} else cpl()
})
adminRoutes.post("/transfer", parser, (req,res) => { adminRoutes.post("/transfer", parser, (req,res) => {
if (!auth.validate(req.cookies.auth)) { if (!auth.validate(req.cookies.auth)) {

View file

@ -92,7 +92,6 @@ export function delFile(optPicker) {
]).then((exp) => { ]).then((exp) => {
if (exp && exp.selected) { if (exp && exp.selected) {
fetch(`/admin/delete`,{method:"POST", body:JSON.stringify({ fetch(`/admin/delete`,{method:"POST", body:JSON.stringify({
owner: exp.owner,
target: exp.file target: exp.file
})}).then((response) => { })}).then((response) => {
@ -103,4 +102,92 @@ export function delFile(optPicker) {
}) })
} }
}) })
}
export function elevateUser(optPicker) {
optPicker.picker("Elevate user",[
{
name: "Username",
icon: "/static/assets/icons/person.svg",
id: "user",
inputSettings: {}
},
{
name: "Elevate to admin",
icon: "/static/assets/icons/admin/update.svg",
id: true
}
]).then((exp) => {
if (exp && exp.selected) {
fetch(`/admin/elevate`,{method:"POST", body:JSON.stringify({
target: exp.user
})}).then((response) => {
if (response.status != 200) {
optPicker.picker(`${response.status} ${response.statusText}`,[])
}
})
}
})
}
// im really lazy so i just stole this from account.js
export function deleteAccount(optPicker) {
optPicker.picker("What should we do with the target account's files?",[
{
name: "Delete files",
icon: "/static/assets/icons/admin/delete_file.svg",
description: "Files will be permanently deleted",
id: true
},
{
name: "Do nothing",
icon: "/static/assets/icons/file.svg",
description: "Files will not be affected",
id: false
}
]).then((exp) => {
if (exp) {
let deleteFiles = exp.selected
optPicker.picker(`Enter the target account's username to continue.`,[
{
name: "Enter account username",
icon: "/static/assets/icons/person.svg",
inputSettings: {},
id:"username"
},
{
name: "Optional reason",
icon: "/static/assets/icons/more.svg",
inputSettings: {},
id:"reason"
},
{
name: `Delete account ${deleteFiles ? "& its files" : ""}`,
icon: "/static/assets/icons/delete_account.svg",
description: `This cannot be undone.`,
id: true
}
]).then((fin) => {
if (fin && fin.selected) {
fetch(`/admin/delete_account`,{method:"POST", body:JSON.stringify({
target: fin.username,
reason: fin.reason,
deleteFiles
})}).then((response) => {
if (response.status != 200) {
optPicker.picker(`${response.status} ${response.statusText}`,[])
}
fetchAccountData()
})
}
})
}
})
} }

View file

@ -198,7 +198,7 @@
<p>Admin</p> <p>Admin</p>
</div> </div>
<button> <button on:click={() => admOpts.deleteAccount(optPicker)}>
<img src="/static/assets/icons/delete_account.svg" alt="delete account"> <img src="/static/assets/icons/delete_account.svg" alt="delete account">
<p>Delete user account</p> <p>Delete user account</p>
</button> </button>
@ -208,7 +208,7 @@
<p>Change user password</p> <p>Change user password</p>
</button> </button>
<button> <button on:click={() => admOpts.elevateUser(optPicker)}>
<img src="/static/assets/icons/admin/elevate_user.svg" alt="elevate account"> <img src="/static/assets/icons/admin/elevate_user.svg" alt="elevate account">
<p>Elevate account to admin</p> <p>Elevate account to admin</p>
</button> </button>
@ -223,11 +223,6 @@
<p>Delete file</p> <p>Delete file</p>
</button> </button>
<button>
<img src="/static/assets/icons/update.svg" alt="update">
<p>Update files from before monofile 1.3<span><br />This may take a while</span></p>
</button>
{/if} {/if}
<p style="font-size:12px;color:#AAAAAA;text-align:center;" class="monospace"><br />{$account.id}</p> <p style="font-size:12px;color:#AAAAAA;text-align:center;" class="monospace"><br />{$account.id}</p>
</div> </div>